home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / midi / misc / Midi2TeX / src / tp_m2t13.pas < prev    next >
Pascal/Delphi Source File  |  1992-11-30  |  111KB  |  3,094 lines

  1. {$R+,S+,D+,F+}
  2. {$DEFINE PC}  (* activate for DOS machines *)
  3. { $DEFINE ST} (* activate for ST machine *)
  4. program TP_M2T13;
  5. (******************************************************************)
  6. (*       Deze versie is voor MusicTeX                             *)
  7. (*                                                                *)
  8. (*                                                                *)
  9. (*                                 19-5-92                        *)
  10. (******************************************************************)
  11.    
  12.  
  13. uses    TP_M2TF2,
  14.         DOS,
  15.         Printer,
  16. {$IFDEF ST}
  17.         GemAES,         
  18. {$ENDIF}
  19.         TP_Decl,
  20.         TP_Misc,
  21.         TP_Heap1,
  22.         TP_debug,
  23.         TP_MIDI;
  24.         
  25.  
  26. (*************************************************************)
  27.     Procedure   NewErrorExit;
  28. (*************************************************************)
  29. Begin
  30. If ExitCode>0 Then
  31.    Begin
  32.    If MIDIFileOpened Then
  33.       WriteLn(TexFile,'% MIDI2TeX processing ended due to runtime error');
  34.    ToBothEr(' Wait a minute, this was a runtime error, of type : '+I2S(ExitCode));
  35.    End;
  36.  
  37. If MidiFileOpened Then
  38.     Begin
  39.     Close(MidiFile);
  40.     Close(TexFile);
  41.     (* FreeMem(TexBuf,SizeOf(BufType)); this seems to be not necessary *)
  42.     WriteDebugInfo('Closing Midi & Tex File...');
  43.     End;
  44. If DebugFileOpened Then 
  45.     Begin
  46.     Close(DebugFile);
  47.     (* FreeMem(DebBuf,SizeOf(BufType)); this seems to be not necessary *)
  48.     If Debug Then WriteLn('Closing up Debugging logger...');
  49.     End;
  50. KillNotePool;
  51. KillNoteLists;
  52. For i:=1 To NoTracks Do
  53.      KillFilRec(TrackArray[i].FilRec);
  54. {$IFDEF ST}
  55.  If NOT BatchProcessing then 
  56.     Begin
  57.     WriteLn('Hit key to exit');
  58.     Repeat until KeyPressed;
  59.     End;
  60. {$ENDIF}
  61. ExitProc:=OldExitProc;
  62. End; (* NewErrorExit *)
  63.  
  64. (*************************************************************)
  65.     Procedure   InstallNewErrorExit;
  66. (*************************************************************)
  67. Begin
  68. OldExitProc:=ExitProc;
  69. ExitProc:=@NewErrorExit;
  70. End; (* InstallNewErrorExit *)
  71.  
  72.  
  73. (*************************************************************)
  74.     Function CheckChordNotes(Note1,Note2:NoteRecord):Boolean;
  75. (*                                                           *)
  76. (*  This function checks if notes 1 and 2 form a chord       *)
  77. (*************************************************************)
  78. CONST  eps=3;
  79.     
  80. Begin
  81. Case TimeDiff(Note1.StartTime,Note2.StartTime) OF
  82.     -eps..eps : If Note1.NoteType=Note2.NoteType Then 
  83.                     CheckChordNotes:=TRUE
  84.                 Else
  85.                     CheckChordNotes:=FALSE;
  86.     Else 
  87.          CheckChordNotes:=FALSE;
  88. End; (* case *)         
  89. End; (* CheckChordNotes *)
  90.  
  91.  
  92.  
  93. (********************************************************)
  94.     Function  NoteLength(ThisNote : NoteRecord):LongInt;
  95. (********************************************************)
  96. Begin
  97. With ThisNote DO NoteLength:=TimeDiff(EndTime,StartTime);
  98. End;
  99.  
  100.  
  101.  
  102. (**************************************************************)
  103.       Procedure ResetChordArray(VAR ThisStack : ChordArrayType);
  104. (*************************************************************)
  105. Begin
  106. FillChar(ThisStack,SizeOf(ChordArrayType),0);
  107. End;
  108.  
  109. (**************************************************************)
  110.       Procedure ResetBeamArray(VAR ThisArray : BeamArrayType);
  111. (*************************************************************)
  112. Begin
  113. FillChar(ThisArray,SizeOf(BeamArrayType),0);
  114. End;
  115.  
  116. (**************************************************************)
  117.       Procedure ResetAccKeys;
  118. (*************************************************************)
  119. Var i : Integer;
  120. Begin
  121. For i:=1 to ntracks do
  122.    With TrackArray[i] Do FillChar(AccKey,SizeOf(AccKeyType),0);
  123. End;
  124.  
  125.  
  126. (******************************************************)
  127.       Procedure SortChord(VAR ThisTrack: TrackRecord;
  128.                           VAR ThisChord: ChordRecord);
  129. (******************************************************)
  130. VAR  mn,mx,k,mean  : Integer;
  131.      N,P,Nmx,Nmn   : NoteRecPoint;
  132.      Border        : Integer;
  133. Begin
  134. mn:=32000; mx:=0; mean:=0; k:=0;
  135. With ThisTrack Do
  136.     Begin
  137.     N:=ThisChord.StartNote;
  138.     NextNote(ThisChord.EndNote,P);
  139.     Repeat
  140.        Inc(mean,N^.NoteVal);
  141.        Inc(k);
  142.        if N^.NoteVal>mx Then
  143.           Begin mx:=N^.NoteVal; Nmx:=N; End;
  144.        if N^.NoteVal<mn Then
  145.           Begin mn:=N^.NoteVal; Nmn:=N; End;
  146.        NextNote(N,N);
  147.     until N=P;
  148.     mean:=mean div k;
  149.  
  150.     Case ThisTrack.Clef Of
  151.           VIOLIN : Border:=70;
  152.           BASS   : Border:=52 ;
  153.        End;
  154.  
  155.     if mean>Border then  (* put lowest last , staff should be down *)
  156.        Begin
  157.        If (ThisCHord.EndNote<>Nmn) Then
  158.           Begin
  159.           WriteDebugInfo('Exchanging note '+B2S(ThisCHord.EndNote^.NoteVal)+' with '+B2S(Nmn^.NoteVal));
  160.           With ThisCHord Do If STartNote=Nmn Then StartNote:=EndNote; (* else ???*)
  161.           Exchange(NoteList,Nmn,ThisChord.EndNote);
  162.           ThisChord.EndNote^.CHordNote:=TRUE;
  163.           Nmn^.ChordNote:=FALSE;
  164.           Nmn^.Orient:=DOWN;
  165.           ThisChord.EndNote:=Nmn;
  166.           End
  167.        Else
  168.           WriteDebugInfo('No sort necessary')
  169.        End
  170.     Else       (* put highest note last, staff should be up *)
  171.        Begin
  172.        If (ThisCHord.EndNote<>Nmx) Then
  173.            Begin
  174.            WriteDebugInfo('Exchanging note '+B2S(ThisCHord.EndNote^.NoteVal)+' with '+B2S(Nmx^.NoteVal));
  175.            With ThisCHord Do If STartNote=Nmx Then StartNote:=EndNote;
  176.            Exchange(NoteList,Nmx,ThisChord.EndNote);
  177.            ThisChord.EndNote^.CHordNote:=TRUE;
  178.            Nmx^.ChordNote:=FALSE;
  179.            Nmx^.Orient:=UP;
  180.            ThisChord.EndNote:=Nmx;
  181.            End
  182.        Else
  183.            WriteDebugInfo('No sort necessary');
  184.        End;
  185.     End; (* with thistrack *)
  186. End; (* SortChord *)
  187.  
  188.  
  189.  
  190. (******************************************************)
  191.       Procedure ChordFind(VAR ThisTrack: TrackRecord);
  192. (******************************************************)
  193.  
  194. CONST
  195.     eps = 0.1;
  196. VAR 
  197.     dstart   :  LongInt;
  198.     VoidNotes:  Byte;
  199.     N,P,Q    :  NoteRecPoint;
  200.     Chording :  Boolean;
  201. Begin
  202. WriteDebugInfo('Starting ChordFind');
  203. Chording:=FALSE;
  204. With ThisTrack Do
  205.     Begin
  206.     ChStackPoint:=1;
  207.     ChStackEnd:=1;
  208.     VoidNotes:=0;
  209.     FirstNote(NoteList,N);
  210.     FirstNote(NoteList,P);
  211.     Repeat
  212.         Begin
  213.  
  214.         CASE N^.Event Of
  215.           REST : Begin (* this should end any pending chords *) end;
  216.           VOID : INC(VoidNotes);
  217.           NOTEON,NOTEOFF :
  218.            Begin
  219.            If NOT Chording Then
  220.                With ChordArray[ChStackPoint] DO
  221.                    Begin
  222.                    StartNote:=N;
  223.                    N^.ChordNote:=TRUE;
  224.                    NoNotes:=1;
  225.                    Chording:=TRUE;
  226.                    End
  227.            Else (* if Chording *)
  228.                Begin
  229.                PrevNote(N,Q);
  230.                dstart:=TimeDiff(N^.StartTime,Q^.StartTime);
  231.                If (N^.NoteType=Q^.NoteType)
  232.                   AND (dstart<QuantTime) Then
  233.                    Begin (* notetypes and starttimes are equal *)
  234.                    With ChordArray[ChStackPoint] DO
  235.                        Begin
  236.                        WriteDebugInfo('Note '+W2S(N^.NoteVal)+' in chord');
  237.                        N^.ChordNote:=TRUE;
  238.                        EndNote:=N;
  239.                        INC(NoNotes);
  240.                        End;
  241.                    End
  242.                Else
  243.                    Begin (* note types or starttimes are not equal *)
  244.                    If ChordArray[ChStackPoint].NoNotes >1 Then
  245.                        Begin (* there was a chord on the stack *)
  246.                        
  247.                        WriteDebugInfo('Finishing up a chord..');
  248.                        
  249.                        ChordArray[ChStackPoint].ChordFinished:=TRUE;
  250.                       (* start a possible beam at this chord's note *)
  251.                        WITH ChordArray[ChStackPoint] DO                            
  252.                             EndNote^.ChordNote:=FALSE;
  253.  
  254.                        INC(ChStackPoint);
  255.                        WITH ChordArray[ChStackPoint] DO
  256.                             Begin
  257.                             N^.ChordNote:=TRUE;
  258.                             StartNote:=N;
  259.                             INC(NoNotes);
  260.                             End;
  261.                        End
  262.                    Else
  263.                        Begin (* there was no chord on the stack *)
  264.                        WITH ChordArray[ChStackPoint] DO
  265.                            Begin
  266.                            StartNote^.ChordNote:=FALSE;
  267.                            N^.ChordNote:=TRUE;
  268.                            StartNote:=N;
  269.                            NoNotes:=1;
  270.                            End;
  271.                        End;
  272.                    End;
  273.               End;
  274.            End; (* Event=NOTEON,NOTEOFF *)
  275.            End; (* End Case *)
  276.            NextNote(N,N);
  277.            End; (* repeat loop *)
  278.         Until N=P; (* FirstNote(NoteList) *)
  279.         
  280.     WriteDebugInfo('Processed all events in the notelist');
  281.     
  282.     Case ChordArray[ChStackPoint].NoNotes of 
  283.     2..10    :Begin  (* finish up chord *)
  284.               With ChordArray[ChStackPoint] DO
  285.                 Begin
  286.                 ChordFinished:=TRUE;
  287.                 EndNote^.ChordNote:=FALSE;
  288.                 End;
  289.               ChStackEnd:=ChStackPoint
  290.               End;
  291.     1        :Begin  (* Cancel the one-note-chord *)
  292.               With ChordArray[ChStackPoint] Do
  293.                  Begin
  294.                  StartNote^.ChordNote:=FALSE;
  295.                  StartNote:=NIL;
  296.                  End;
  297.               Dec(ChStackPoint);
  298.               ChStackEnd:=ChStackPoint
  299.               End;
  300.     0        :Begin (* there are no notes in the stack *)
  301.               Dec(ChStackPoint);
  302.               ChStackEnd:=ChStackPoint    
  303.               End;          
  304.     END; (* CASE *)              
  305.  
  306.     END; (* WITH *)
  307. With ThisTrack Do
  308.      Begin
  309.      WriteDebugInfo('Resorting '+W2S(ChStackEnd)+' Chord(s) in this measure');
  310.      (* WriteDebugInfo('Before sort: '+NoteList2String(NoteList)); *)
  311.      WriteDebugInfo('Before sort: '+ChordNoteList2String(NoteList));
  312.      For i:=1 To ChStackEnd Do
  313.         Begin
  314.         SortChord(ThisTrack,ChordArray[i]);
  315.         End;
  316.      (* WriteDebugInfo('After sort: '+NoteList2String(NoteList)); *)
  317.      WriteDebugInfo('After sort: '+ChordNoteList2String(NoteList));
  318.      End;
  319. WriteDebugInfo('Number of void notes found in this measure by chordfind:'+B2S(VoidNotes));
  320. WriteDebugInfo('ChordFind ready');
  321. End; (* ChordFind *)
  322.  
  323. (******************************************************)
  324.     function FindSlurrIndex : Integer;
  325. (******************************************************)
  326. VAR i : Integer;
  327. Begin
  328. i:=0;
  329. While (SlurrIndexes[i]) AND (i<MAXSLURR) do INC(i);
  330. If i>=MAXSLURR Then ErrorExit(16);
  331. SlurrIndexes[i]:=TRUE;
  332. FindSlurrIndex:=i;
  333. End;
  334.  
  335. (*********************************************************)
  336.     function  IsSlurred(N : NoteRecPoint;
  337.                              ThisTrack: TrackRecord): Integer;
  338. (******************************************************)
  339. VAR i : Integer;
  340.     B : Integer;
  341. Begin
  342. B:=0;
  343. WIth Thistrack Do
  344.    Begin
  345.    For i:=1 To SlurrPt Do
  346.        With SlurrArray[i] Do
  347.          If Occupied and (NotePnt=N) Then
  348.             B:=i;
  349.    End;
  350. IsSlurred:=B;
  351. End;
  352.  
  353.  
  354. (********************************************************)
  355.     Procedure FindSlurrNote(VAR ThisTrack : TrackRecord;
  356.                                 CurMeasure: Integer);
  357. (********************************************************)
  358. VAR
  359.     N,P                 : NoteRecPoint;
  360.     SlurrI1,SlurrI2     :integer;
  361.     TmpTime             : MeasureTime;
  362. Begin
  363. WriteDebugInfo('Starting SlurrFinder');
  364. SetTime(TmpTime,CurMeasure+1,0);
  365. With ThisTrack DO
  366.   Begin
  367.   FirstNote(NoteList,N);
  368.   P:=N;
  369.   Repeat
  370.   Begin
  371.      With N^ Do
  372.        Case  Event Of
  373.          REST   : (* A rest occurred, their ought not to be any slurrs *)
  374.                  Begin
  375.                  End;
  376.          NOTEON,
  377.          NOTEOFF:
  378.               If TimeDiff(TmpTime,EndTime)<0 Then
  379.                  (* The EndTime of this note is beyond the end of current measure *)
  380.                  (* So, slurr this note *)
  381.                  Begin
  382.                  SlurrI2:=IsSlurred(N,ThisTrack);
  383.                  If SlurrI2=0 Then (* was not already slurred *)
  384.                     Begin
  385.                     SlurrI1:=FindSlurrIndex;
  386.                     Inc(SlurrPt);
  387.                     With SlurrArray[SlurrPt] Do
  388.                         Begin
  389.                         WriteDebugInfo('At note '+B2S(N^.NoteVal)+' a startslurr');
  390.                         NotePnt:=N;
  391.                         NoteVal:=N^.NoteVal;
  392.                         KindOf:=STARTSLUR;
  393.                         Numb1:=SlurrI1;
  394.                         Occupied:=TRUE;
  395.                         End;
  396.                     Slurring:=TRUE;
  397.                     (*Slurring:=FALSE;*) (* this disables slurring for test purpose *)
  398.                     End (* If SlurrI2=0 *)
  399.                  Else
  400.                     Begin
  401.                     (* Note was already slurred.  *)
  402.                     SlurrI1:=FindSlurrIndex;
  403.                     With SlurrArray[SlurrPt] Do
  404.                         Begin
  405.                         WriteDebugInfo('At note '+B2S(N^.NoteVal)+' a repeatslurr');
  406.                         KindOF:=REPEATSLUR;
  407.                         Numb2:=Numb1;
  408.                         Numb1:=SlurrI1;
  409.                         End;
  410.                     End;
  411.                  End
  412.               Else
  413.                  (* The EndTime of this note is in current measure *)
  414.                  If Slurring Then
  415.                     Begin
  416.                     SlurrI2:=IsSlurred(N,ThisTrack);
  417.                     If SlurrI2>0 Then (* this note was slurred *)
  418.                       With SlurrArray[SlurrI2] Do
  419.                         Begin
  420.                         WriteDebugInfo('At note '+B2S(N^.NoteVal)+' end slurr');
  421.                         KindOf:=ENDSLUR;
  422.                         Numb2:=Numb1;
  423.                         End
  424.                     End;
  425.        End; (* case *)
  426.      NextNote(N,N);
  427.      End;
  428.      Until N=P; (* FirstNote(NoteList) *)
  429.   End; (* with TrackList *)
  430. End; (* FindSlurrNote*)
  431.  
  432.  
  433. (******************************************************************)
  434.     Procedure ChopRest(VAR N: NoteRecPoint;VAR ThisTrack : TrackRecord;
  435.                             ThisMsre      : Integer);
  436. (******************************************************************)
  437. VAR   P  : NoteRecPoint;
  438.       dt : LongInt;
  439.       TmpTime : MeasureTime;
  440.       DivTime,
  441.       divider : word;
  442.       cnt     : Byte;
  443. Begin
  444. WriteDebugInfo('Starting ChopRest ');
  445.  
  446. SetTime(TmpTime,ThisMsre+1,0);
  447. dt:=TimeDiff(N^.EndTime,TmpTime);
  448. if dt>0 Then (* Rest is longer than and of current measure *)
  449.    Begin
  450.    WriteDebugInfo('Chopping rest off at end of this measure');
  451.    P:=GetFreeNote;
  452.    Insert(ThisTrack.NoteList,N^.Next,P);
  453.    P^.EndTime:=N^.EndTime;
  454.    P^.StartTime:=TmpTime; N^.EndTime:=TmpTime;   
  455.    P^.Event:=REST;
  456.    End;
  457. dt:=TimeDiff(N^.EndTime,N^.StartTime);
  458. divtime:=8*PieceCOntr.Division;
  459. cnt:=0;
  460. While dt>4*PieceContr.Division div 32 Do   
  461.    Begin
  462.    Divider:=0;
  463.    While Divider=0 Do 
  464.       Begin
  465.       divtime:=divtime SHR 1;
  466.       divider:=dt div divtime;
  467.       inc(cnt);  
  468.       End;
  469.    SetTime(TmpTime,0,divtime);
  470.    AddTime(N^.StartTime,TmpTime,TmpTime);
  471.    N^.NoteType:=NoteTypes(cnt);
  472.    dt:=dt - Divider*DivTime;
  473.    if dt>4*PieceContr.Division div 64 Then
  474.       Begin
  475.       P:=GetFreeNote;
  476.       Insert(ThisTrack.NoteList,N^.Next,P);
  477.       P^.Event:=REST;
  478.       P^.EndTime:=N^.EndTime;
  479.       N^.EndTime:=TmpTime;   
  480.       P^.StartTime:=TmpTime;
  481.       WriteDebugInfo('Chopping rest into: ['+I2S(N^.StartTime.Measure)+':'+LI2S(N^.StartTime.MPart)+'-'
  482.                      +I2S(N^.EndTime.Measure)+':'+LI2S(N^.EndTime.MPart)+']and ['
  483.                      +I2S(P^.StartTime.Measure)+':'+LI2S(P^.StartTime.MPart)+'-'
  484.                      +I2S(P^.EndTime.Measure)+':'+LI2S(P^.EndTime.MPart)+']');
  485.       N:=P;
  486.       End;      
  487.    End; (* while *)   
  488. WriteDebugInfo('End ChopRest');   
  489. End; (* ChopRest *)
  490.  
  491.  
  492. (******************************************************)
  493.     Procedure FindNoteTypes(VAR ThisTrack : TrackRecord;
  494.                             ThisMsre      : Integer);
  495. (******************************************************)
  496. VAR
  497.     N,P     : NoteRecPoint;
  498.     dt      : Longint;
  499.     Divisor,
  500.     Rst    :  Integer;
  501.     SlurrI1,SlurrI2:integer;
  502.     TmpTime : MeasureTime;
  503. Begin
  504. With ThisTrack DO
  505.   Begin
  506.   FirstNote(NoteList,N);
  507.   P:=N;
  508.   Repeat
  509.   Begin
  510.      With N^ Do
  511.        Begin
  512.  
  513.        Case Event Of
  514.           NOTEON,NOTEOFF : Case Clef Of
  515.                              VIOLIN : If NoteVal>70 Then Orient:=DOWN Else Orient:=UP;
  516.                              BASS   : If NoteVal>52 Then Orient:=DOWN Else Orient:=UP;
  517.                            End;
  518.        End;
  519.  
  520.        Case  Event Of
  521.          NOTEON :
  522.               Begin
  523.               WriteDebugInfo('Found a non-closed note');
  524.               WriteDebugInfo('Starting at '+W2S(StartTime.Measure)+':'+
  525.                               W2S(StartTime.MPart));
  526.               WriteDebugInfo('Ending at '+W2S(EndTime.Measure)+':'+
  527.                               W2S(EndTime.MPart));
  528.               (* this prevent that the endtimes (1000) of non-closed notes *)
  529.               (* faul up the selection of the notetype *)
  530.               SetTime(TmpTime,ThisMsre+1,0);
  531.               End;
  532.          Else 
  533.               Begin
  534.               (* if the note ends in this measure, check if its length is *)
  535.               (* longer than a whole note *)
  536.               (* check if a noteoff is shut off in this measure *)
  537.               SetTime(TmpTime,ThisMsre+1,0);
  538.               dt:=TimeDiff(TmpTime,EndTime);
  539.               if dt>=0 Then (* Note is closed in this measure ... *)
  540.                   TmpTime:=EndTime;              
  541.               End;     
  542.        End; (* case *)
  543.  
  544.  
  545.            If Quantizing Then Quantize(N);
  546.  
  547.            (* DO not use EndTime but the previously defined TmpTime *)
  548.            dt:=TimeDiff(TmpTime,StartTime);
  549.            if dt<0 Then
  550.               WriteDebugInfo('Found an event with neg length !');
  551.            If dt>0 Then
  552.                 With PieceContr DO
  553.                     If Division>dt Then
  554.                         Begin
  555.                         Divisor:=Division div dt;
  556.                         Rst:=10*(Division mod dt) div dt;
  557.                         Case Divisor  OF
  558.                             1   :   Case Rst OF
  559.                                        0..2    : Notetype:=Q;
  560.                                        3,4     : NoteType:=CP;
  561.                                        5..9    : NoteType:=C;
  562.                                     End;
  563.                             2   :   Case Rst OF
  564.                                        0..4    : NoteType:=C;
  565.                                        5..8    : NoteType:=CCP;
  566.                                        9       : NoteType:=C3;
  567.                                      End;
  568.                             3   :   Case Rst OF
  569.                                        0..4    : (* 1/8 trioler *)
  570.                                                  NoteType:=C3;
  571.                                        5..9    : NoteType:=CC;
  572.                                     End;
  573.                             4   :   NoteType:=CC;
  574.                             5,6 :   (* 1/16 trioler *)
  575.                                     NoteType:=CC3;
  576.                             7..12 : NoteType:=CCC;
  577.                             Else    NoteType:=CCCC;
  578.                           End;
  579.                         End
  580.                     Else (* if Division<dt *)
  581.                         Begin
  582.                         Divisor:=dt div Division;
  583.                         Rst:=10*(dt mod Division ) div Division;
  584.                            Case  Divisor Of
  585.                             1   :   Case Rst OF
  586.                                        0..1 : NoteType:=Q;
  587.                                        2..3 : (* These notes should be slurred  *)
  588.                                               NoteType:=QPP;
  589.                                        4..6 : NoteType:=QP;
  590.                                        7,8  : NoteType:=QP; (* should be longer *)
  591.                                        9    : NoteType:=H;
  592.                                     End;
  593.                             2   :   Case Rst OF (* dit klopt nog niet ... *)
  594.                                        0..1 : NoteType:=H;
  595.                                        2..3 : NoteType:=HPPP;
  596.                                        4..6 : NoteType:=HPP;
  597.                                        7,8  : NoteType:=HP;
  598.                                        9    : NoteType:=HP;
  599.                                     End;
  600.                             3   :   Case Rst OF
  601.                                        0..4 : NoteType:=HP;
  602.                                        5..9 : NoteType:=WH;
  603.                                     End;
  604.                             4   :   Case Rst OF
  605.                                     0..3   :  NoteType:=WH;
  606.                                     4..9   :  NoteType:=WHPP;
  607.                                     End;
  608.                             5   :   NoteType:=WHPP;
  609.                             6   :   NoteType:=WHP;
  610.                         End;
  611.                         End
  612.            Else
  613.                Begin
  614.                (* Do not show note, it has length zero ! *)
  615.                If Event=TXT Then 
  616.                   WriteDebugInfo('Hey, here is that metatext again..')
  617.                Else
  618.                  Begin              
  619.                  Event:=VOID;
  620.                  WriteDebugInfo('Found a void note');
  621.                  End;
  622.                End;
  623.          (* If Event=REST Then ChopRest(N,ThisTrack,ThisMsre); *)
  624.          End; (* WIth N^ *)
  625.      NextNote(N,N);
  626.      End;
  627.      Until N=P; (* FirstNote(NoteList) *)
  628.   End; (* with TrackList *)
  629. End; (* FindNoteTypes *)
  630.  
  631. (*********************************************************************)
  632.   Function NoteInChord(N:NoteRecPoint;ThisTrack:TrackRecord):Integer;
  633. (*********************************************************************)
  634. VAR i : Byte;
  635. Begin
  636. NoteInChord:=0;
  637. With ThisTrack DO
  638.   For i:=1 to ChStackEnd Do
  639.      If ChordArray[i].StartNote=N Then NoteInChord:=i;
  640. End;
  641.  
  642.  
  643. (******************************************************)
  644.    Procedure BeamFind(VAR ThisTrack : TrackRecord);
  645. (******************************************************)
  646. VAR
  647.     BeamPnt   :  Byte;
  648.     NotePnt,
  649.     FirstPnt,
  650.     LastPnt   :  NoteRecPoint;
  651.     Beaming   :  Boolean;
  652.  
  653. (*--------------------*)
  654.   Procedure StartBeam;
  655. (*--------------------*)
  656. Begin
  657. With ThisTrack.BeamArray[BeamPnt] Do
  658.    Begin
  659.    StartNote:=NotePnt;
  660.    EndNote:=NotePnt;
  661.    NoteType:=NotePnt^.NoteType;
  662.    Beaming:=TRUE;
  663.    NoNotes:=1;
  664.    Numb:=BeamIndex;
  665.    Inc(BeamIndex);
  666.    WriteDebugInfo('Starting beam '+B2S(Numb)+' at note '+B2S(NotePnt^.NoteVal)+
  667.                   ' of type '+B2S(Ord(NoteType)));
  668.    End;
  669. End;
  670.  
  671. (*--------------------*)
  672.   Procedure EndBeam;
  673. (*--------------------*)
  674. VAR  mn,i : word;
  675.      cnt,BPnt,
  676.      max,min : Byte;
  677.      N,P     : NoteRecPoint;
  678.      GoOn    : Boolean;
  679. Begin
  680. With ThisTrack.BeamArray[BeamPnt] Do
  681.    Begin
  682.    Beaming:=FALSE;
  683.    Chain2Next:=FALSE;
  684.    End;
  685.  
  686. mn:=0; Max:=0; Min:=127; cnt:=0; BPnt:=BeamPnt;
  687. (* Pitch and slope should be determined over all chained beams *)
  688.  
  689. (* first, from the top find the first beam which has CHain2Next flag set *)
  690. GoOn:=FALSE;
  691. If BPnt>1 Then Dec(Bpnt);
  692. While NOT GoOn Do
  693.   Begin
  694.   If (ThisTrack.BeamArray[BPnt].Chain2Next) AND (BPnt>1) Then Dec(BPnt)
  695.   Else Begin
  696.        If (NOT ThisTrack.BeamArray[BPnt].Chain2Next) Then
  697.           If (Bpnt<BeamPnt) Then Inc(Bpnt);
  698.        GoOn:=TRUE;
  699.        End;
  700.   End;
  701.  
  702. (* The first Chain2Next Beam is pointed to by BPnt *)
  703. (* We now have to process all the notes in the beams until BPnt=BeamPnt *)
  704.  
  705. For i:=Bpnt To BeamPnt Do
  706.    Begin
  707.    With ThisTrack.BeamArray[i] Do
  708.       Begin
  709.       N:=StartNote;
  710.       NextNote(EndNote,P);
  711.       Repeat
  712.         Begin
  713.         (*If NOT N^.ChordNote Then*)
  714.         Case N^.Event Of
  715.            NOTEON,NOTEOFF :
  716.               Begin
  717.               mn:=mn+N^.NoteVal;
  718.               inc(cnt);
  719.               If N^.NoteVal>Max Then Max:=N^.NoteVal;
  720.               If N^.NoteVal<Min Then Min:=N^.NoteVal;
  721.               End;
  722.         End; (* case *)
  723.         NextNote(N,N);
  724.         End;
  725.       until N=P;
  726.       End; (* With *)
  727.    End; (* For *)
  728.  
  729. (* mn,cnt,Max and Min now have values  calculated over all Chained beams *)
  730. (* We now have to fill the first beam record (Bpnt) with these values *)
  731.  
  732.    (* This routine now does not take in account the orient of the note   *)
  733.    (* itself set by FindNotes and ChordFind. Look at this again...       *)
  734.    (* When handling chords, the mean only sees single notes of the chord.*)
  735.    (* So that messes up a lot. *)
  736.  
  737. With ThisTrack.BeamArray[Bpnt] Do
  738.     Begin
  739.     mn:=mn Div cnt;
  740.     Case ThisTrack.Clef Of
  741.        VIOLIN : If mn<70 Then Orient:=UP Else Orient:=DOWN;
  742.        BASS   : If mn<52 Then Orient:=UP Else Orient:=DOWN;
  743.     End;
  744.     If ORIENT=UP Then Pitch:=Max ELse Pitch:=Min;
  745.  
  746.     If EndNote^.NoteVal>StartNote^.NoteVal Then
  747.        Slope:=(Max-Min) div cnt
  748.     Else
  749.        Slope:=-(Max-Min) div cnt;
  750.     (* WriteDebugInfo('Beam '+B2S(BeamPnt)+' has pitch '+B2S(Pitch)+
  751.                    ',max='+B2S(max)+' min='+B2S(min)); *)
  752.     If Orient=UP Then
  753.        WriteDebugInfo('Ending beam '+B2S(Numb)+', beam is UP')
  754.     Else
  755.        WriteDebugInfo('Ending beam '+B2S(Numb)+', beam is DOWN');
  756.     End; (* with thistrack.beamarray *)
  757.  
  758. (* Now Pitch,Orient & Slope must be copied to all Chained beams *)
  759. For i:=BPnt+1 To BeamPnt Do
  760.    Begin
  761.    ThisTrack.BeamArray[i].Orient:=ThisTrack.BeamArray[i-1].Orient;
  762.    ThisTrack.BeamArray[i].Slope:=ThisTrack.BeamArray[i-1].SLope;
  763.    ThisTrack.BeamArray[i].Pitch:=ThisTrack.BeamArray[i-1].Pitch;
  764.    End;
  765.  
  766. INC(BeamPnt);
  767. If BeamPnt>MAXBEAMS Then ErrorExit(18);
  768. End;
  769.  
  770. (*--------------------*)
  771. Procedure CancelBeam;
  772. (*--------------------*)
  773. Begin
  774. Beaming:=FALSE;
  775. With ThisTrack.BeamArray[BeamPnt] Do
  776.   Begin
  777.   StartNote:=NIL;
  778.   EndNote:=NIL;
  779.   NoNotes:=0;
  780.   WriteDebugInfo('Canceling beam '+B2S(Numb)+' at note '+B2S(NotePnt^.NoteVal));
  781.   End;
  782. End;
  783.  
  784. (*--------------------*)
  785.  Procedure QuitBeam;
  786. (*--------------------*)
  787. (* Close up the beams. Cancel Beam only if previous beam *)
  788. (* has Chain2Next flag not set OR if BeamPnt=1 *)
  789. Begin
  790. With ThisTrack Do
  791.    If BeamArray[BeamPnt].NoNotes=1 Then
  792.       Begin
  793.       If BeamPnt=1 Then
  794.         CancelBeam
  795.       Else If BeamArray[BeamPnt-1].Chain2Next Then
  796.               EndBeam
  797.            Else CancelBeam
  798.       End
  799.    Else
  800.       EndBeam;
  801. End; (* QuitBeam *)
  802.  
  803. (*--------------------*)
  804. Procedure Add2Beam;
  805. (*--------------------*)
  806. Begin
  807. With ThisTrack.BeamArray[BeamPnt] Do
  808.    Begin
  809.    Inc(NoNotes);
  810.    EndNote:=NotePnt;
  811.    End;
  812. End;
  813.  
  814. (*--------------------------*)
  815.   Procedure CreateUpChainBeam;
  816. (*--------------------------*)
  817. Begin
  818. With ThisTrack.BeamArray[BeamPnt] Do
  819.    Begin
  820.    Chain2Next:=TRUE;
  821.    EndNote:=NotePnt;
  822.    End;
  823. INC(BeamPnt);
  824. If BeamPnt>MAXBEAMS Then ErrorExit(18);
  825. With ThisTrack.BeamArray[BeamPnt] Do
  826.    Begin
  827.    StartNote:=NotePnt;
  828.    EndNote:=NotePnt;
  829.    NoteType:=NotePnt^.NoteType;
  830.    Numb:=BeamIndex-1;
  831.    Beaming:=TRUE;
  832.    NoNotes:=1;
  833.    WriteDebugInfo('Chain  beam '+B2S(Numb)+' at note '+B2S(NotePnt^.NoteVal)+
  834.                   ' to type '+B2S(Ord(NoteType)));
  835.    End;
  836. End; (* CreateUpChainBeam *)
  837.  
  838. (*--------------------------*)
  839.   Procedure CreateDnChainBeam;
  840. (*--------------------------*)
  841. Begin
  842. With ThisTrack.BeamArray[BeamPnt] Do
  843.    Begin
  844.    Chain2Next:=TRUE;
  845.    End;
  846. INC(BeamPnt);
  847. If BeamPnt>MAXBEAMS Then ErrorExit(18);
  848. With ThisTrack.BeamArray[BeamPnt] Do
  849.    Begin
  850.    StartNote:=NotePnt;
  851.    EndNote:=NotePnt;
  852.    NoteType:=NotePnt^.NoteType;
  853.    Numb:=BeamIndex-1;
  854.    Beaming:=TRUE;
  855.    NoNotes:=1;
  856.    WriteDebugInfo('Chain beam '+B2S(Numb)+' at note '+B2S(NotePnt^.NoteVal)+
  857.                   ' to type '+B2S(Ord(NoteType)));
  858.    End;
  859. End; (* CreateDnChainBeam *)
  860.  
  861.  
  862. Begin (* BeamFind *)
  863. WriteDebugInfo('Starting BeamFind');
  864. BeamPnt:=1;
  865. Beaming:=FALSE;
  866.  
  867. With ThisTrack DO
  868.   Begin
  869.   FirstNote(NoteList,NotePnt);
  870.   FirstPnt:=NIL; (* prevent early termination *)
  871.  
  872.   While NotePnt<>FirstPnt DO
  873.    Begin (* while *)
  874.    FirstNote(NoteList,FirstPnt);
  875.    CASE NotePnt^.Event OF
  876.    NOTEON,NOTEOFF: 
  877.     If NOT NotePnt^.ChordNote Then (* exclude non-spacing notes *)   
  878.      Begin
  879.      WriteDebugInfo('Note '+B2S(NotePnt^.NoteVal)+' is of type '+
  880.                     B2S(Ord(NotePnt^.NoteType)));
  881.      If Beaming Then
  882.           Case BeamArray[BeamPnt].NoteType Of
  883.               CPPP..C     :  Case NotePnt^.NoteType Of
  884.                                 CC3..CCCC  :   CreateUpChainBeam;
  885.                                 CPPP..C    :   Add2Beam;
  886.                              Else
  887.                                 QuitBeam;
  888.                              End;
  889.               CC3..CC     :  Case NotePnt^.NoteType Of
  890.                                 CPPP..C    :   CreateDnChainBeam;
  891.                                 CCC3..CCCC :   CreateUpChainBeam;
  892.                                 CC3..CC    :   Add2Beam;
  893.                              Else
  894.                                 QuitBeam;
  895.                              End;
  896.               CCC3..CCC   :  Case NotePnt^.NoteType Of
  897.                                 CPPP..CC       :   CreateDnChainBeam;
  898.                                 CCCC3..CCCC    :   CreateUpChainBeam;
  899.                                 CCC3..CCC      :   Add2Beam;
  900.                              Else
  901.                                 QuitBeam;
  902.                               End;
  903.               CCCC3..CCCC3:   Case NotePnt^.NoteType Of
  904.                                 CPPP..CCC   :   CreateDnChainBeam;
  905.                                 CCCC3..CCCC3:   Add2Beam;
  906.                               Else
  907.                                 QuitBeam;
  908.                               End;
  909.           Else
  910.               QuitBeam;
  911.           End (* Case under If Beaming *)
  912.  
  913.      Else
  914.  
  915.          Begin (* not Beaming *)
  916.          If NotePnt^.NoteType>CPP Then
  917.             StartBeam;
  918.          End; (* not Beaming *)
  919.  
  920.      End; (* NOTEON,NOTEOFF *)
  921.      End; (* CASE N^.Event OF *)
  922.      NextNote(NotePnt,NotePnt);
  923.      End; (* WHILE *)
  924.   End; (* with thistrack *)
  925.  
  926.  
  927. If Beaming Then QuitBeam;
  928.  
  929. WriteDebugInfo('BeamFind Ready');
  930. End; (* BeamFind *)
  931.  
  932.  
  933.  
  934. (**********************************************)
  935.     Procedure InitFilePosns(N:Integer);       
  936. (**********************************************)
  937.  
  938. VAR i,dummy  : Byte;
  939.     cnt,
  940.     NoOfBytes,
  941.     OldPos : LongInt;
  942.     TmpStr : String;
  943. Begin
  944. i:=1;
  945. (* OldPos:=FilePos(MidiFile); *)
  946. repeat 
  947.     TmpStr:=ReadString(HlpFilRec,4);
  948.     WriteDebugInfo(' Found start of track '+B2S(i)+' with name:'+TmpStr);
  949.     NoOfBytes:=ReadLongInt(HlpFilRec);
  950.     (*WriteDebugInfo('FIlePos:'+LI2S(GetFilePos(HlpFilRec))); *)
  951.     WriteDebugInfo(LI2S(NoOfBytes)+' bytes in this track');
  952.     With TrackArray[i] DO
  953.         Begin
  954.         (* Copy the file info stuff into the currentr track file info *)
  955.         FilRec.FilePosition:=HlpFilRec.FilePosition;
  956.         Move(HlpFilRec.ReadBuf^,FilRec.ReadBuf^,BufSize);
  957.         EndOfTrackRead:=FALSE;
  958.         FilRec.BytesProcessed:=0;
  959.         FilRec.BufSemaphore:=HlpFilRec.BufSemaphore;
  960.         FilRec.BufPoint:=HlpFilRec.BufPoint;
  961.         FilRec.LastBlockRead:=HlpFilRec.LastBlockRead;
  962.         SafetyCounter:=0;
  963.         FillChar(CurTime,SizeOf(CurTime),0);
  964.         FillChar(OldTime,SizeOf(CurTime),0);
  965.         End;
  966.     For cnt:=1 to NoOfBytes Do dummy:=ReadByte(HlpFilRec);    
  967.     (*WriteDebugInfo('FIlePos:'+LI2S(GetFilePos(HlpFilRec))); *)
  968.     INC(i);
  969. until i=N+1;  
  970. (* Seek(MidiFile,OldPos); *)
  971. End;  (* InitFilePosns *) 
  972.  
  973. (**********************************************)
  974.    Function AllTracksRead(N:integer) : Boolean;
  975. (**********************************************)
  976. VAR b : boolean;
  977.     i : integer;
  978. Begin
  979. b:=TRUE;
  980. For i:=1 To N Do 
  981.    If NOT EndOfTrackReached(TrackArray[i])Then b:=FALSE;
  982. AllTracksRead:=b;
  983. End;
  984.  
  985.  
  986. (**********************************************)
  987.    Procedure InitFileDebug;
  988. (**********************************************)
  989. Var FilesSel,
  990.     Pcnt,i,j: Byte;
  991.     PS,S    : String;
  992.     Sint,
  993.     Serr    : Integer;
  994.  
  995. (*--------------------------------------------------------------*)
  996.   Procedure ReadFileName(VAR ThisFile : FileNameType; path : String);
  997. (*--------------------------------------------------------------*)
  998. Begin
  999. With ThisFile Do
  1000.   Begin
  1001.   p:=path;
  1002.   Fsplit(p,d,n,e);
  1003.   If e='' Then 
  1004.      If FilesSel=0 Then e:='.MID' Else e:='.TEX';
  1005.   p:=d+n+e;
  1006.   INC(FilesSel);
  1007.   End;
  1008. End; (* ReadFileName *)
  1009.  
  1010. (*--------------------------------------------------------------*)
  1011.   Function SplitHead(VAR PS : String) : integer;
  1012. (*--------------------------------------------------------------*)
  1013. VAR j,Sint,Serr : Integer;
  1014.     S           : String[3];
  1015. Begin
  1016. j:=Pos(',',PS);
  1017. Case j Of
  1018. 1..10 : Begin
  1019.         S:=Copy(PS,1,j-1);
  1020.         Delete(PS,1,j);
  1021.         End;
  1022. Else
  1023.         S:=Copy(PS,1,Length(PS));
  1024.         Delete(PS,1,Length(PS));
  1025. End; (* case *)
  1026.  
  1027. Val(S,Sint,Serr);
  1028. If Serr=0 Then SplitHead:=Sint Else SplitHead:=-1;
  1029. End; (* SplitHead *)
  1030.  
  1031. Begin
  1032. FilesSel:=0;
  1033. DebugOut:=NODEB;
  1034. Debug:=FALSE;
  1035.       For PCnt:=1 To ParamCount Do      
  1036.          Begin
  1037.          (* WriteLn('Paramstring=',ParamStr(PCnt)); *)
  1038.          PS:=ParamStr(PCnt);
  1039.          If Copy(PS,1,1)='-' Then
  1040.          Begin
  1041.             If Copy(PS,1,2)='-?' Then
  1042.                 Begin
  1043.                 ErrorExit(0);
  1044.                 End;
  1045. {$IFDEF ST}
  1046.             If Copy(PS,1,2)='-x' Then
  1047.                 Begin
  1048.                 BatchProcessing:=TRUE;
  1049.                 End;
  1050. {$ENDIF}
  1051.             If Copy(PS,1,2)='-i' Then
  1052.                 Begin (* determine instrument staffs *)
  1053.                 If (ninstruments>0) Then ErrorExit(14);
  1054.                 INC(ninstruments);
  1055.                 Delete(PS,1,2);
  1056.                 IF Length(PS)<3 Then ErrorExit(15);
  1057.                 while Length(PS)>0 Do
  1058.                    Begin 
  1059.                    
  1060.                    j:=Pos(',',PS);
  1061.                    Case j Of 
  1062.                    1..10 : Begin
  1063.                            S:=Copy(PS,1,j-1);                
  1064.                            Delete(PS,1,j);
  1065.                            End;
  1066.                    Else           
  1067.                            S:=Copy(PS,1,Length(PS));
  1068.                            Delete(PS,1,Length(PS));
  1069.                    End; (* case *) 
  1070.                       
  1071.                    Val(S,Sint,Serr);
  1072.                    If Serr=0 Then 
  1073.                        Begin
  1074.                        TrackArray[Sint].Instrument:=TRUE;
  1075.                        INC(NtracksInInstr);
  1076.                        WriteDebugInfo('Track :'+I2S(Sint)+' is part of an instrument');
  1077.                        End;
  1078.                    End;
  1079.                 End; (* if switch='-i' *)
  1080.                 
  1081.             If Copy(PS,1,2)='-f' Then
  1082.                 Begin (* force zero beams for these staffs *)
  1083.                 Delete(PS,1,2);                
  1084.                 while Length(PS)>0 Do
  1085.                    Begin 
  1086.                    
  1087.                    j:=Pos(',',PS);
  1088.                    Case j Of 
  1089.                    1..10 : Begin
  1090.                            S:=Copy(PS,1,j-1);                
  1091.                            Delete(PS,1,j);
  1092.                            End;
  1093.                    Else           
  1094.                            S:=Copy(PS,1,Length(PS));
  1095.                            Delete(PS,1,Length(PS));
  1096.                    End; (* case *) 
  1097.                       
  1098.                    Val(S,Sint,Serr);
  1099.                    If Serr=0 Then 
  1100.                        Begin
  1101.                        TrackArray[Sint].ForceZeroBeams:=TRUE;
  1102.                        WriteDebugInfo('Track :'+I2S(Sint)+' has beam slope forced to zero');
  1103.                        End;
  1104.                    End;
  1105.                 End; (* if switch='-f' *)
  1106.  
  1107.             If Copy(PS,1,2)='-h' Then
  1108.                 Begin (* change horizontal size *)
  1109.                 Delete(PS,1,2);
  1110.                 while Length(PS)>0 Do
  1111.                    Begin 
  1112.                    
  1113.                    j:=Pos(',',PS);
  1114.                    Case j Of 
  1115.                    1..10 : Begin
  1116.                            ErrorExit(19);
  1117.                            End;
  1118.                    Else           
  1119.                            S:=Copy(PS,1,Length(PS));
  1120.                            Delete(PS,1,Length(PS));
  1121.                    End; (* case *) 
  1122.                       
  1123.                    Val(S,Sint,Serr);
  1124.                    If Serr=0 Then 
  1125.                        Begin
  1126.                        scorewidth:=Sint;
  1127.                        SizingChanged:=TRUE;
  1128.                        WriteDebugInfo('Changing scorewidth from default to '+I2S(scorewidth));
  1129.                        End;
  1130.                    End;
  1131.                 End; (* if switch='-h' *)
  1132.  
  1133.             If Copy(PS,1,2)='-v' Then
  1134.                 Begin (* change vertical size *)
  1135.                 Delete(PS,1,2);
  1136.                 while Length(PS)>0 Do
  1137.                    Begin 
  1138.                    
  1139.                    j:=Pos(',',PS);
  1140.                    Case j Of 
  1141.                    1..10 : Begin
  1142.                            ErrorExit(19);
  1143.                            End;
  1144.                    Else           
  1145.                            S:=Copy(PS,1,Length(PS));
  1146.                            Delete(PS,1,Length(PS));
  1147.                    End; (* case *) 
  1148.                       
  1149.                    Val(S,Sint,Serr);
  1150.                    If Serr=0 Then 
  1151.                        Begin
  1152.                        scoreheight:=Sint;
  1153.                        SizingChanged:=TRUE;
  1154.                        WriteDebugInfo('Changing scoreheight from default to '+I2S(scoreheight));
  1155.                        End;
  1156.                    End;
  1157.                 End; (* if switch='-v' *)
  1158.  
  1159.             If Copy(PS,1,2)='-e' Then
  1160.                 Begin (* change elemskip value *)
  1161.                 Delete(PS,1,2);
  1162.                 while Length(PS)>0 Do
  1163.                    Begin 
  1164.                    
  1165.                    j:=Pos(',',PS);
  1166.                    Case j Of 
  1167.                    1..10 : Begin
  1168.                            ErrorExit(19);
  1169.                            End;
  1170.                    Else           
  1171.                            S:=Copy(PS,1,Length(PS));
  1172.                            Delete(PS,1,Length(PS));
  1173.                    End; (* case *) 
  1174.                       
  1175.                    Val(S,Sint,Serr);
  1176.                    If Serr=0 Then 
  1177.                        Begin
  1178.                        Elemskip:=Round(Sint*PT);
  1179.                        SizingChanged:=TRUE;
  1180.                        WriteDebugInfo('Changing Elemskip from default to '+I2S(Elemskip));
  1181.                        End;
  1182.                    End;
  1183.                 End; (* if switch='-e' *)
  1184.  
  1185.             If Copy(PS,1,2)='-m' Then
  1186.                 Begin (* change magnitude of score *)
  1187.                 Delete(PS,1,2);
  1188.                 while Length(PS)>0 Do
  1189.                    Begin
  1190.  
  1191.                    j:=Pos(',',PS);
  1192.                    Case j Of
  1193.                    1..10 : Begin
  1194.                            ErrorExit(19);
  1195.                            End;
  1196.                    Else
  1197.                            S:=Copy(PS,1,Length(PS));
  1198.                            Delete(PS,1,Length(PS));
  1199.                    End; (* case *)
  1200.  
  1201.                    Val(S,Sint,Serr);
  1202.                    If Serr=0 Then
  1203.                        Begin
  1204.                        Case Sint Of
  1205.                            20 : Begin MusicSize:=20;
  1206.                                       LineHeight:=160;
  1207.                                       ScoreSep:=20;
  1208.                                       Indent:=115;
  1209.                                       CumLength:=215; 
  1210.                                       BarIndent:=40;
  1211.                                       ElemSkip:=Round(10*PT);
  1212.                                 End;
  1213.                            16 : Begin MusicSize:=16;
  1214.                                       LineHeight:=125;
  1215.                                       ScoreSep:=40;
  1216.                                       Indent:=90;
  1217.                                       CumLength:=190;
  1218.                                       BarIndent:=30;
  1219.                                       ElemSkip:=Round(8*PT);
  1220.                                 End;
  1221.                            Else ErrorExit(20);
  1222.                        End; (* case *)
  1223.                        SizingChanged:=TRUE;
  1224.                        WriteDebugInfo('Changing magnitude from default to '+I2S(Sint));
  1225.                        End;
  1226.                    End;
  1227.                 End; (* if switch='-m' *)
  1228.  
  1229.             If Copy(PS,1,2)='-k' Then
  1230.                 Begin (* change keysign of score *)
  1231.                 Delete(PS,1,2);
  1232.                 while Length(PS)>0 Do
  1233.                    Begin
  1234.  
  1235.                    j:=Pos(',',PS);
  1236.                    Case j Of
  1237.                    1..10 : Begin
  1238.                            ErrorExit(19);
  1239.                            End;
  1240.                    Else
  1241.                            S:=Copy(PS,1,Length(PS));
  1242.                            Delete(PS,1,Length(PS));
  1243.                    End; (* case *)
  1244.  
  1245.                    Val(S,Sint,Serr);
  1246.                    If Serr=0 Then
  1247.                        Begin
  1248.                        Case Sint Of
  1249.                            -8..8 : Begin
  1250.                                    PieceContr.KeySign:=Sint;
  1251.                                    End;
  1252.                             Else ErrorExit(21);
  1253.                        End; (* case *)
  1254.                        WriteDebugInfo('Changing keysign to '+I2S(Sint));
  1255.                        End;
  1256.                    End;
  1257.                 End; (* if switch='-k' *)
  1258.  
  1259.  
  1260.             If Copy(PS,1,2)='-q' Then
  1261.                 Begin (* determine quantization *)
  1262.                 Delete(PS,1,2);
  1263.                 Val(PS,Sint,Serr);
  1264.                 If (Serr=0) AND (Sint<=64) AND (Sint>0) Then
  1265.                     Begin
  1266.                     Quantizing:=TRUE;
  1267.                     QuantTime:=Sint;
  1268.                     End
  1269.                 Else
  1270.                     ErrorExit(13);
  1271.                 End; (* if switch='-q' *)
  1272.  
  1273.             If Copy(PS,1,2)='-b' Then
  1274.                 Begin (* determine bass clefs *)
  1275.                 Delete(PS,1,2);
  1276.                 while Length(PS)>0 Do
  1277.                    Begin 
  1278.                    
  1279.                    j:=Pos(',',PS);
  1280.                    Case j Of 
  1281.                    1..10 : Begin
  1282.                            S:=Copy(PS,1,j-1);                
  1283.                            Delete(PS,1,j);
  1284.                            End;
  1285.                    Else           
  1286.                            S:=Copy(PS,1,Length(PS));
  1287.                            Delete(PS,1,Length(PS));
  1288.                    End; (* case *) 
  1289.                       
  1290.                    Val(S,Sint,Serr);
  1291.                    If Serr=0 Then 
  1292.                        Begin
  1293.                        TrackArray[Sint].Clef:=BASS;
  1294.                        WriteDebugInfo('Track :'+I2S(Sint)+' notated with bass clef');
  1295.                        End;
  1296.                    End;
  1297.                 End; (* if switch='-b' *)
  1298.  
  1299.             If Copy(PS,1,3)='-a1' Then
  1300.                 Begin (* determine ALTO1 clefs *)
  1301.                 Delete(PS,1,3);
  1302.                 while Length(PS)>0 Do
  1303.                    Begin 
  1304.                    Sint:=SplitHead(PS);
  1305.                    If Sint>0 Then TrackArray[Sint].Clef:=ALTO1
  1306.                    Else ErrorExit(22);
  1307.                    WriteDebugInfo('Track :'+I2S(Sint)+' notated with ALTO1 clef');
  1308.                    End;
  1309.                 End; (* if switch='-a1' *)
  1310.  
  1311.             If Copy(PS,1,3)='-a2' Then
  1312.                 Begin (* determine ALTO2 clefs *)
  1313.                 Delete(PS,1,3);
  1314.                 while Length(PS)>0 Do
  1315.                    Begin 
  1316.                    Sint:=SplitHead(PS);
  1317.                    If Sint>0 Then TrackArray[Sint].Clef:=ALTO2
  1318.                    Else ErrorExit(22);
  1319.                    WriteDebugInfo('Track :'+I2S(Sint)+' notated with ALTO2 clef');
  1320.                    End;
  1321.                 End; (* if switch='-a2' *)
  1322.  
  1323.             If Copy(PS,1,3)='-a3' Then
  1324.                 Begin (* determine ALTO3 clefs *)
  1325.                 Delete(PS,1,3);
  1326.                 while Length(PS)>0 Do
  1327.                    Begin 
  1328.                    Sint:=SplitHead(PS);
  1329.                    If Sint>0 Then TrackArray[Sint].Clef:=ALTO3
  1330.                    Else ErrorExit(22);
  1331.                    WriteDebugInfo('Track :'+I2S(Sint)+' notated with ALTO3 clef');
  1332.                    End;
  1333.                 End; (* if switch='-a3' *)
  1334.  
  1335.             If Copy(PS,1,3)='-a4' Then
  1336.                 Begin (* determine ALTO4 clefs *)
  1337.                 Delete(PS,1,3);
  1338.                 while Length(PS)>0 Do
  1339.                    Begin 
  1340.                    Sint:=SplitHead(PS);
  1341.                    If Sint>0 Then TrackArray[Sint].Clef:=ALTO4
  1342.                    Else ErrorExit(22);
  1343.                    WriteDebugInfo('Track :'+I2S(Sint)+' notated with ALTO4 clef');
  1344.                    End;
  1345.                 End; (* if switch='-a4' *)
  1346.  
  1347.  
  1348.             If Copy(PS,1,2)='-o' Then
  1349.                 Begin (* order staffs *)
  1350.                 Delete(PS,1,2);
  1351.                 while Length(PS)>0 Do
  1352.                    Begin 
  1353.                    
  1354.                    j:=Pos(',',PS);
  1355.                    Case j Of 
  1356.                    1..10 : Begin
  1357.                            S:=Copy(PS,1,j-1);                
  1358.                            Delete(PS,1,j);
  1359.                            End;
  1360.                    Else           
  1361.                            S:=Copy(PS,1,Length(PS));
  1362.                            Delete(PS,1,Length(PS));
  1363.                    End; (* case *) 
  1364.                       
  1365.                    Val(S,Sint,Serr);
  1366.                    If Serr=0 Then 
  1367.                        Begin
  1368.                        TrackOrder[OrderIndex]:=Sint;
  1369.                        WriteDebugInfo('Ordering MIDI Track :'+I2S(Sint)+' at Staff '+B2S(OrderIndex));
  1370.                        Inc(OrderIndex);
  1371.                        End;
  1372.                    End;
  1373.                 Dec(OrderIndex) (* now pointing at last item in orderarray *)
  1374.                 End; (* if switch='-o' *)
  1375.  
  1376.  
  1377.             If Copy(PS,1,2)='-s' Then
  1378.                 Begin
  1379.                 Delete(PS,1,2);
  1380.                 while Length(PS)>0 Do
  1381.                    Begin 
  1382.                    
  1383.                    j:=Pos(',',PS);
  1384.                    Case j Of 
  1385.                    1..10 : Begin
  1386.                            S:=Copy(PS,1,j-1);                
  1387.                            Delete(PS,1,j);
  1388.                            End;
  1389.                    Else           
  1390.                            S:=Copy(PS,1,Length(PS));
  1391.                            Delete(PS,1,Length(PS));
  1392.                    End; (* case *) 
  1393.                       
  1394.                    Val(S,Sint,Serr);
  1395.                    If Serr=0 Then 
  1396.                        Begin
  1397.                        If Sint=1 Then
  1398.                           Begin
  1399.                           TrackArray[Sint].Skip:=FALSE;
  1400.                           DEC(NoOfSkips);
  1401.                           End
  1402.                        Else
  1403.                          Begin
  1404.                          Inc(TrackArray[Sint].Skip);
  1405.                          INC(NoOfSkips);
  1406.                          End;
  1407.                        WriteDebugInfo('Skipping Track :'+I2S(Sint));                    
  1408.                        End
  1409.                    Else
  1410.                        ErrorExit(23);
  1411.                    End;
  1412.                 End; (* skip tracks *)
  1413.  
  1414.             If Copy(PS,1,2)='-p' Then
  1415.                 Begin
  1416.                 Delete(PS,1,2);
  1417.                 while Length(PS)>0 Do
  1418.                    Begin 
  1419.                    
  1420.                    j:=Pos(',',PS);
  1421.                    Case j Of 
  1422.                    1..10 : Begin
  1423.                            S:=Copy(PS,1,j-1);                
  1424.                            Delete(PS,1,j);
  1425.                            End;
  1426.                    Else           
  1427.                            S:=Copy(PS,1,Length(PS));
  1428.                            Delete(PS,1,Length(PS));
  1429.                    End; (* case *) 
  1430.                       
  1431.                    Val(S,Sint,Serr);
  1432.                    If Serr=0 Then 
  1433.                        Begin
  1434.                        Case Sint of
  1435.                           1,2,4,8,16,32 : Begin
  1436.                                           PieceContr.PartType:=Sint;
  1437.                                           WriteDebugInfo('Part Timing ='+I2S(Sint));
  1438.                                           PieceContr.PartOverRule:=TRUE;
  1439.                                           End;
  1440.                           Else  ErrorExit(12);
  1441.                        End;
  1442.                        End;
  1443.                    End;
  1444.                 End; (* PartTime *)
  1445.  
  1446.             If Copy(PS,1,2)='-d' Then
  1447.                 Begin
  1448.                 If Copy(PS,3,length(PS)-2)='FILE' Then
  1449.                      Begin
  1450.                      If MaxAvail>SizeOf(BufType) Then
  1451.                          GetMem(DebBuf,SizeOf(BufType))
  1452.                      Else
  1453.                          ErrorExit(9);
  1454.  
  1455.    {$IFDEF PC}
  1456.                      Assign(DebugFile,DebugFileName.p);
  1457.                      ReWrite(DebugFile);
  1458.                      SetTextBuf(DebugFile,DebBuf);
  1459.    {$ENDIF}
  1460.    {$IFDEF ST}
  1461.                      ReWrite(DebugFile,DebugFileName.p,BufSize);
  1462.    {$ENDIF}                  
  1463.                      DebugFileOpened:=TRUE;
  1464.                      DebugOut:=DEBFILE;
  1465.                      Debug:=TRUE;
  1466.                      End;
  1467.                 If Copy(PS,3,length(PS)-2)='PRINTER' Then
  1468.                      Begin
  1469.                      DebugOut:=PRINT;
  1470.                      Debug:=TRUE;
  1471.                      End;
  1472.                 If Copy(PS,3,length(PS)-2)='SCREEN' Then
  1473.                      Begin
  1474.                      DebugOut:=SCREEN;
  1475.                      Debug:=TRUE;
  1476.                      End;
  1477.                 End;
  1478.                 End (* If this parameter is a switch *) 
  1479.               Else
  1480.                 Begin (* this parameter is not a switch *)
  1481.  
  1482.                 If FilesSel=0 Then
  1483.                    Begin
  1484.                    ReadFileName(MidiFileName,PS);
  1485.                    DebugFileName:=MidiFileName;
  1486.                    With DebugFileName Do
  1487.                       Begin
  1488.                       e:='.MLG';
  1489.                       p:=d+n+e;
  1490.                       End;
  1491.                    End
  1492.                 Else
  1493.                    ReadFileName(TeXFileName,PS);
  1494.  
  1495.                 End; (* else *)
  1496.          End; (* for next loop *)
  1497.  
  1498. If NOT FileExists(MidiFileName.p) Then ErrorExit(1);
  1499. If FilesSel=1 Then (* there was no TeXFilename selected *)
  1500.    Begin
  1501.    TeXFileName:=MidiFileName;
  1502.    With TeXFileName do
  1503.       Begin
  1504.       e:='.TEX';
  1505.       p:=d+n+e;
  1506.       End;
  1507.    End;
  1508.  
  1509.   If MaxAvail>SizeOf(BufType) Then
  1510.       GetMem(TexBuf,SizeOf(BufType))
  1511.   Else
  1512.       ErrorExit(9);
  1513.  
  1514.  
  1515. {$IFDEF ST}
  1516.   Reset(MidiFile,MidiFileName.p);
  1517.   Rewrite(TexFile,TexFileName.p,BufSize);
  1518. {$ENDIF}
  1519.  
  1520. {$IFDEF PC}
  1521.   Assign(MidiFile,MidiFileName.p);
  1522.   Reset(MidiFile,1);
  1523.   Assign(TexFile,TexFileName.p);
  1524.   Rewrite(TexFile);
  1525.   SetTextBuf(TexFile,TexBuf);
  1526. {$ENDIF}
  1527.   MidiFileOpened:=TRUE;
  1528.   With MIDIFileName Do
  1529.   Write('Translating ',d+n+e,' into ');
  1530.   With TeXFileName Do
  1531.   WriteLn(d+n+e);
  1532.   WriteDebugInfo('***********************************************');
  1533.   WriteDebugInfo('*            Midi2TeX translator '+Version+'        *');
  1534.   WriteDebugInfo('*                   by                        *');
  1535.   WriteDebugInfo('*              Hans Kuykens                   *');
  1536.   With MidiFileName Do
  1537.   WriteDebugInfo('* Translating '+d+n+e);
  1538.   WriteDebugInfo('*                  into ');
  1539.   With TeXFileName Do
  1540.   WriteDebugInfo('*             '+d+n+e);
  1541.   WriteDebugInfo('***********************************************');
  1542.  
  1543. End; (* InitFileDebug *)
  1544.  
  1545. (**********************************************)
  1546.    Procedure Initialize;
  1547. (**********************************************)
  1548. Begin
  1549. MidiFileOpened:=FALSE;
  1550. DebugFileOpened:=FALSE;
  1551. DebugFileOpened:=FALSE;
  1552. InitNotePool;
  1553. FillChar(PieceContr,SizeOf(ControlInfo),0);
  1554. For i:=1 to NoTracks Do
  1555.   Begin
  1556.   FillChar(TrackArray[i],SizeOf(TrackRecord),0);
  1557.   End;
  1558.   
  1559. For i:=1 To NoTracks Do
  1560.      InitFilRec(TrackArray[i].FilRec);
  1561. InitFilRec(HlpFilRec);
  1562. For i:=1 To NoTracks Do
  1563.    TrackOrder[i]:=i;
  1564. For i:=0 to MAXSLURR do
  1565.     SlurrIndexes[i]:=FALSE;
  1566. TrackArray[1].SKip:=TRUE; (* Always  skip track 1 *)
  1567. OrderIndex:=1;
  1568. NoOfSkips:=1;
  1569. PieceContr.PartOverRule:=FALSE;
  1570. Quantizing:=FALSE;
  1571. TeXHeaderFinished:=FALSE;
  1572. ninstruments:=0;
  1573. nTracksInInstr:=0;
  1574. ScoreWidth:=1600;  (* 0.1 mm *) (* MusicTeX standard *)
  1575. ScoreHeight:=2400; (* 0.1 mm *)
  1576. LineHeight:=160;   (* 0.1 mm *)
  1577. ElemSkip:=Round(10*PT);  (* 3.5 mm *) (* STandard \elemskip *)
  1578. CumLength:=220;      (* initialize cumulative length and height  *)
  1579. Indent:=115;
  1580. BarIndent:=40;
  1581. ScoreSep:=20;
  1582. MeasureMaxCnt:=0;  (* Maximum number of notes in a measure     *)
  1583. MusicSize:=20;
  1584. SizingChanged:=FALSE;
  1585. BatchProcessing:=FALSE;
  1586. NoOfPages:=1;
  1587. QuantTime:=16; (* default value *)
  1588. InitFileDebug;
  1589. End; (* Initialize *)
  1590.  
  1591. (*****************************************************)
  1592.     Procedure CleanUpSlurrArrays;
  1593. (*****************************************************)
  1594. VAR i,j,TmpIndx  : integer;
  1595. Begin
  1596. TmpIndx:=0;
  1597. For j:=1 to ntracks do
  1598.    With TrackArray[j] do
  1599.       Begin
  1600.       i:=1;
  1601.       While i<=SlurrPt Do
  1602.          Begin
  1603.          if NOT SlurrArray[i].Occupied Then (* is processed, remove... *)
  1604.             Begin
  1605.             WriteDebugInfo('Removing slurr #'+I2S(SlurrArray[i].Numb2));
  1606.             SlurrIndexes[SlurrArray[i].Numb2]:=FALSE;
  1607.             If i<MAXSLURR Then
  1608.                Begin
  1609.                Move(SlurrArray[i+1],SlurrArray[i],(MAXSLURR-i)*SizeOf(SlurrRecord));
  1610.                Dec(i); Dec(SlurrPt); (* dit werkt niet !!! *)
  1611.                End
  1612.             Else
  1613.                Begin
  1614.                FillChar(SlurrArray[i],SizeOf(SlurrRecord),0);
  1615.                Dec(SlurrPt);
  1616.                End
  1617.             End;
  1618.          INC(i);
  1619.          End;
  1620.        If SlurrPt<0 Then SlurrPt:=0; (* for safety *)
  1621.        If SlurrPt=0 Then Slurring:=FALSE;
  1622.       End;
  1623. End;
  1624.  
  1625.  
  1626.  
  1627. (************************************************************)
  1628.     Procedure CleanUpTracks;
  1629. (************************************************************)
  1630. VAR N,P : NoteRecPoint;
  1631.     All,i   : integer;
  1632.     curtrack  : Byte;
  1633.     TmpTime   : MeasureTime;
  1634. Begin
  1635. SetTime(TmpTime,MeasureCount+1,0);
  1636. for curtrack:=1 to ntracks do
  1637.     With TrackArray[curtrack] Do
  1638.         Begin
  1639.         All:=NoteList.Size;
  1640.         LastNote(NoteList,N);
  1641.         PrevNote(N,P);
  1642.         For i:=1 To All Do
  1643.             Begin
  1644.             Case N^.Event Of              
  1645.              VOID     :  Begin
  1646.                          Remove(NoteList,N);
  1647.                          BringFreeNote(N);
  1648.                          End; (* if notearry *)
  1649.              REST,            
  1650.              NOTEOFF  :  Begin
  1651.                          If TimeDiff(TmpTime,N^.EndTime)<0 Then
  1652.                              Begin
  1653.                              WriteDebugInfo('Extending event '+B2S(N^.NoteVal)+
  1654.                              ' into next measure');
  1655.                              SetTime(N^.StartTime,MeasureCount+1,0);
  1656.                              End
  1657.                          Else
  1658.                              Begin
  1659.                              Remove(NoteList,N);
  1660.                              BringFreeNote(N);
  1661.                              End
  1662.                          End;
  1663.              NOTEON   :  SetTime(N^.StartTime,MeasureCount+1,0);
  1664.              TXT      :  Begin
  1665.                          FreeMem(N^.MetaTxt,SizeOf(String20Type));
  1666.                          Remove(NoteList,N);
  1667.                          BringFreeNote(N);
  1668.                          End;
  1669.              PEDAL,
  1670.              KEYSIGN,
  1671.              SIGNATURE:  Begin
  1672.                          If TimeDiff(TmpTime,N^.StartTime)<0 Then
  1673.                              Begin
  1674.                              WriteDebugInfo('META event '+N^.MetaTxt^+' still on stack...????');
  1675.                              End
  1676.                          Else
  1677.                              Begin
  1678.                              Remove(NoteList,N);
  1679.                              BringFreeNote(N);
  1680.                              End
  1681.                          End;
  1682.  
  1683.             End; (* case *)
  1684.             N:=P;
  1685.             PrevNote(N,P);
  1686.             End;
  1687.         WriteDebugInfo('There are '+W2S(NoteList.Size)+' notes which slurr to next measure');
  1688.         (* If NoteList.Size>0 Then WriteDebugInfo('First note now has value :'+
  1689.                                             B2S(FirstNote(NoteList)^.NoteVal));
  1690.          *)
  1691.  
  1692.     (* Clean up the BeamArray and ChordArray too *)
  1693.  
  1694.         ResetBeamArray(BeamArray);
  1695.         ResetChordArray(ChordArray);
  1696.         ResetAccKeys;
  1697.  
  1698.         End; (* with thistrack *)
  1699. CleanUpSlurrArrays
  1700. End;
  1701.  
  1702.  
  1703. (**************************************************)
  1704.  Function RestString(ValType : NoteTypes;
  1705.                      Clef : ClefType    ) : STRING;
  1706. (**************************************************)
  1707. Var c1,c2 : CHAR;
  1708. Begin
  1709. Case Clef of
  1710.   VIOLIN : Begin c1:='g'; c2:='j'; end;
  1711.   BASS   : Begin c1:='J'; c2:='K'; end;
  1712. End;
  1713.   CASE ValType Of
  1714.      WH     :   RestString:='\pause ';
  1715.      WHP    :   RestString:='\rlap{\qsk\pt '+c2+'}\pause ';
  1716.      WHPP   :   RestString:='\rlap{\qsk\ppt '+c2+'}\pause ';
  1717.      H      :   RestString:='\hpause ';
  1718.      HP     :   RestString:='\rlap{\qsk\pt '+c2+'}\hpause ';
  1719.      HPP    :   RestString:='\rlap{\qsk\ppt '+c2+'}\hpause ';
  1720.      HPPP   :   RestString:='\pause ';
  1721.      Q      :   RestString:='\soupir ';
  1722.      QP     :   RestString:='\pt '+c1+'\soupir ';
  1723.      QPP    :   RestString:='\ppt '+c1+'\soupir ';
  1724.      QPPP   :   RestString:='\pppt '+c1+'\soupir ';
  1725.      C      :   RestString:='\ds ';
  1726.      CP     :   RestString:='\pt '+c1+'\ds ';
  1727.      C3     :   RestString:='\ds ';
  1728.      CPP    :   RestString:='\ppt '+c1+'\ds ';
  1729.      CPPP   :   RestString:='\pppt '+c1+'\ds ';
  1730.      CC     :   RestString:='\qs ';
  1731.      CCP    :   RestString:='\pt '+c1+'\qs ';
  1732.      CCPP   :   RestString:='\ppt '+c1+'\qs ';
  1733.      CC3    :   RestString:='\qs ';
  1734.      CCC    :   RestString:='\qs ';
  1735.      CCCP   :   RestString:=' ';
  1736.      CCC3   :   RestString:=' ';
  1737.      CCCC   :   RestString:=' ';
  1738.      CCCCP  :   RestString:=' ';
  1739.      CCCC3  :   RestString:=' ';
  1740.    End; (* case *)
  1741. End; (* RestString *)
  1742.  
  1743.  
  1744. (**************************************)
  1745.  Function Index (value : Byte) : Byte;
  1746. (**************************************)
  1747. VAR
  1748.     Modulo,
  1749.     TmpIndx : Byte;
  1750.     Okt     : ShortInt;
  1751. Begin
  1752. If Value>127 Then
  1753.    Begin
  1754.    Warning('Found a notevalue exceeding 127, replacing with 60 !');
  1755.    Value:=60;
  1756.    End;
  1757. Okt:=(value-60);
  1758. Okt:=Okt div 12;
  1759. (* WriteDebugInfo('Index->Okt='+I2S(Okt)); *)
  1760. Modulo:=value mod 12;
  1761. (* WriteDebugInfo('Index->Modulo='+I2S(Modulo)); *)
  1762. TmpIndx:=CPosition+7*Okt;
  1763. (* WriteDebugInfo('Index->TmpIndx='+I2S(TmpIndx)); *)
  1764. If Value>60 Then
  1765.     Case modulo of
  1766.          0 : Index:=TmpIndx;
  1767.          2 : Index:=TmpIndx+1;
  1768.          4 : Index:=TmpIndx+2;
  1769.          5 : Index:=TmpIndx+3;
  1770.          7 : Index:=TmpIndx+4;
  1771.          9 : Index:=TmpIndx+5;
  1772.          11: Index:=TmpIndx+6;
  1773.     Else
  1774.          Index:=TmpIndx;
  1775.     End
  1776. Else
  1777.     Begin
  1778.     Case modulo of
  1779.          2 : Index:=TmpIndx-6;
  1780.          4 : Index:=TmpIndx-5;
  1781.          5 : Index:=TmpIndx-4;
  1782.          7 : Index:=TmpIndx-3;
  1783.          9 : Index:=TmpIndx-2;
  1784.          11: Index:=TmpIndx-1;
  1785.     Else
  1786.          Index:=TmpIndx;
  1787.     End
  1788.  
  1789.     End
  1790. End; (* Index *)
  1791.  
  1792.  
  1793.  
  1794. (************************************************************************)
  1795.   Function ValueString(value : Byte;
  1796.                        Control : ControlInfo;
  1797.                        VAR AKey : AccKeyType;
  1798.                        ChangeAKey: Boolean ) : STRING;
  1799. (************************************************************************)
  1800. VAR
  1801.      Modulo : Byte;
  1802.  
  1803. Begin
  1804. Modulo:=value mod 12;
  1805.  
  1806. (* The Accidental records should be in connection with each track, not with  *)
  1807. (* the control structure. In that case this function should include the      *)
  1808. (* track as a parameter.                                                     *)
  1809.  
  1810. With Control Do
  1811. Case modulo of
  1812.   0  : Case KeySign Of
  1813.        -7..-6:   If (Akey.C=NON) Then
  1814.                    Begin
  1815.                    ValueString:='{='+Notes[Index(value) ]+'}';
  1816.                    If ChangeAKey Then Akey.C:=CORRECT;
  1817.                    End
  1818.                  Else
  1819.                    ValueSTring:=Notes[Index(value)];
  1820.         2..8 :   If (Akey.C=NON) Then
  1821.                    Begin
  1822.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1823.                    If ChangeAKey Then Akey.C:=CORRECT;
  1824.                    End
  1825.                  Else
  1826.                    ValueSTring:=Notes[Index(value)];
  1827.         Else     If (Akey.C<>NON) Then
  1828.                    Begin
  1829.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1830.                    If ChangeAKey Then Akey.C:=NON;
  1831.                    End
  1832.                  Else
  1833.                    ValueSTring:=Notes[Index(value)];
  1834.        End; (* case *)
  1835.  
  1836.   1  : Case KeySign Of
  1837.        2..8 : If Akey.C=CORRECT Then
  1838.                  Begin
  1839.                  ValueSTring:='{^'+Notes[Index(value-1)]+'}';
  1840.                  If ChangeAKey Then Akey.C:=NON;
  1841.                  End
  1842.               Else ValueSTring:=Notes[Index(value-1)];
  1843.       -8..-4: If Akey.D=CORRECT Then
  1844.                  Begin
  1845.                  ValueSTring:='{_'+Notes[Index(value+1)]+'}';
  1846.                  If ChangeAKey Then Akey.D:=NON;
  1847.                  End
  1848.               Else ValueSTring:=Notes[Index(value+1)];
  1849.  
  1850.        Else   If Akey.C=SHARP Then ValueSTring:=Notes[Index(value-1)]
  1851.               Else If Akey.D=FLAT Then ValueSTring:=Notes[Index(value+1)]
  1852.               Else
  1853.                  Case KeySIgn Of
  1854.                  -8..-1 : Begin
  1855.                           ValueSTring:='{_'+Notes[Index(value+1) ]+'}';
  1856.                           If ChangeAKey Then Akey.D:=FLAT;
  1857.                           End;
  1858.                  0..8   : Begin
  1859.                           ValueSTring:='{^'+Notes[Index(value-1) ]+'}';
  1860.                           If ChangeAKey Then Akey.C:=SHARP;
  1861.                           End;
  1862.                  End;
  1863.        End; (* Case KeySign *)
  1864.  
  1865.   2  : Case KeySign Of
  1866.        -8..-4:   If (Akey.D=NON) Then
  1867.                    Begin
  1868.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1869.                    If ChangeAKey Then Akey.D:=CORRECT;
  1870.                    End
  1871.                  Else
  1872.                    ValueSTring:=Notes[Index(value)];
  1873.         4..8 :   If (Akey.D=NON) Then
  1874.                    Begin
  1875.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1876.                    If ChangeAKey Then Akey.D:=CORRECT;
  1877.                    End
  1878.                  Else
  1879.                    ValueSTring:=Notes[Index(value)];
  1880.         Else     If (Akey.D<>NON) Then
  1881.                    Begin
  1882.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1883.                    If ChangeAKey Then Akey.D:=NON;
  1884.                    End
  1885.                  Else
  1886.                    ValueSTring:=Notes[Index(value)];
  1887.        End; (* case *)
  1888.  
  1889.   3  : Case KeySign Of
  1890.        4..8 : If Akey.D=CORRECT Then
  1891.                  Begin
  1892.                  ValueSTring:='{^'+Notes[Index(value-1)]+'}';
  1893.                  If ChangeAKey Then Akey.D:=NON;
  1894.                  End
  1895.               Else ValueSTring:=Notes[Index(value-1)];
  1896.       -8..-2: If Akey.E=CORRECT Then
  1897.                  Begin
  1898.                  ValueSTring:='{_'+Notes[Index(value+1)]+'}';
  1899.                  If ChangeAKey Then Akey.E:=NON;
  1900.                  End
  1901.               Else ValueSTring:=Notes[Index(value+1)];
  1902.  
  1903.        Else   If Akey.D=SHARP Then ValueSTring:=Notes[Index(value-1)]
  1904.               Else If Akey.E=FLAT Then ValueSTring:=Notes[Index(value+1)]
  1905.               Else
  1906.                  Case KeySIgn Of
  1907.                  -8..-1 : Begin
  1908.                           ValueSTring:='{_'+Notes[Index(value+1) ]+'}';
  1909.                           If ChangeAKey Then Akey.E:=FLAT;
  1910.                           End;
  1911.                  0..8   : Begin
  1912.                           ValueSTring:='{^'+Notes[Index(value-1) ]+'}';
  1913.                           If ChangeAKey Then Akey.D:=SHARP;
  1914.                           End;
  1915.                  End;
  1916.        End; (* Case KeySign *)
  1917.  
  1918.   4  : Case KeySign Of
  1919.        -7..-2:   If (Akey.E=NON) Then
  1920.                    Begin
  1921.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1922.                    If ChangeAKey Then Akey.E:=CORRECT;
  1923.                    End
  1924.                  Else
  1925.                    ValueSTring:=Notes[Index(value)];
  1926.         6..8 :   If (Akey.E=NON) Then
  1927.                    Begin
  1928.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1929.                    If ChangeAKey Then Akey.E:=CORRECT;
  1930.                    End
  1931.                  Else
  1932.                    ValueSTring:=Notes[Index(value)];
  1933.         Else     If (Akey.E<>NON) Then
  1934.                    Begin
  1935.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1936.                    If ChangeAKey Then Akey.E:=NON;
  1937.                    End
  1938.                  Else
  1939.                    ValueSTring:=Notes[Index(value)];
  1940.        End; (* case *)
  1941.  
  1942.   5  : Case KeySign Of
  1943.        -7 :    If (Akey.F=NON) Then
  1944.                    Begin
  1945.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1946.                    If ChangeAKey Then Akey.F:=CORRECT;
  1947.                    End
  1948.                  Else
  1949.                    ValueSTring:=Notes[Index(value)];
  1950.         1..8 :   If (Akey.F=NON) Then
  1951.                    Begin
  1952.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1953.                    If ChangeAKey Then Akey.F:=CORRECT;
  1954.                    End
  1955.                  Else
  1956.                    ValueSTring:=Notes[Index(value)];
  1957.         Else     If (Akey.F<>NON) Then
  1958.                    Begin
  1959.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1960.                    If ChangeAKey Then Akey.F:=NON;
  1961.                    End
  1962.                  Else
  1963.                    ValueSTring:=Notes[Index(value)];
  1964.        End; (* case *)
  1965.  
  1966.   6  : Case KeySign Of
  1967.        1..8 : If Akey.F=CORRECT Then
  1968.                  Begin
  1969.                  ValueSTring:='{^'+Notes[Index(value-1)]+'}';
  1970.                  If ChangeAKey Then Akey.F:=NON;
  1971.                  End
  1972.               Else ValueSTring:=Notes[Index(value-1)];
  1973.       -8..-5: If Akey.G=CORRECT Then
  1974.                  Begin
  1975.                  ValueSTring:='{_'+Notes[Index(value+1)]+'}';
  1976.                  If ChangeAKey Then Akey.G:=NON;
  1977.                  End
  1978.               Else ValueSTring:=Notes[Index(value+1)];
  1979.  
  1980.        Else   If Akey.F=SHARP Then ValueSTring:=Notes[Index(value-1)]
  1981.               Else If Akey.G=FLAT Then ValueSTring:=Notes[Index(value+1)]
  1982.               Else
  1983.                  Case KeySIgn Of
  1984.                  -8..-1 : Begin
  1985.                           ValueSTring:='{_'+Notes[Index(value+1) ]+'}';
  1986.                           If ChangeAKey Then Akey.G:=FLAT;
  1987.                           End;
  1988.                  0..8   : Begin
  1989.                           ValueSTring:='{^'+Notes[Index(value-1) ]+'}';
  1990.                           If ChangeAKey Then Akey.F:=SHARP;
  1991.                           End;
  1992.                  End;
  1993.        End; (* Case KeySign *)
  1994.  
  1995.   7  : Case KeySign Of
  1996.        -7..-5:   If (Akey.G=NON) Then
  1997.                    Begin
  1998.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  1999.                    If ChangeAKey Then Akey.G:=CORRECT;
  2000.                    End
  2001.                  Else
  2002.                    ValueSTring:=Notes[Index(value)];
  2003.         3..8 :   If (Akey.G=NON) Then
  2004.                    Begin
  2005.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2006.                    If ChangeAKey Then Akey.G:=CORRECT;
  2007.                    End
  2008.                  Else
  2009.                    ValueSTring:=Notes[Index(value)];
  2010.         Else     If (Akey.G<>NON) Then
  2011.                    Begin
  2012.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2013.                    If ChangeAKey Then Akey.G:=NON;
  2014.                    End
  2015.                  Else
  2016.                    ValueSTring:=Notes[Index(value)];
  2017.        End; (* case *)
  2018.  
  2019.   8  : Case KeySign Of
  2020.        3..8 : If Akey.G=CORRECT Then
  2021.                  Begin
  2022.                  ValueSTring:='{^'+Notes[Index(value-1)]+'}';
  2023.                  If ChangeAKey Then Akey.G:=NON;
  2024.                  End
  2025.               Else ValueSTring:=Notes[Index(value-1)];
  2026.       -8..-3: If Akey.A=CORRECT Then
  2027.                  Begin
  2028.                  ValueSTring:='{_'+Notes[Index(value+1)]+'}';
  2029.                  If ChangeAKey Then Akey.A:=NON;
  2030.                  End
  2031.               Else ValueSTring:=Notes[Index(value+1)];
  2032.  
  2033.        Else   If Akey.G=SHARP Then ValueSTring:=Notes[Index(value-1)]
  2034.               Else If Akey.A=FLAT Then ValueSTring:=Notes[Index(value+1)]
  2035.               Else
  2036.                  Case KeySIgn Of
  2037.                  -8..0  : Begin
  2038.                           ValueSTring:='{_'+Notes[Index(value+1) ]+'}';
  2039.                           If ChangeAKey Then Akey.A:=FLAT;
  2040.                           End;
  2041.                  1..8   : Begin
  2042.                           ValueSTring:='{^'+Notes[Index(value-1) ]+'}';
  2043.                           If ChangeAKey Then Akey.G:=SHARP;
  2044.                           End;
  2045.                  End;
  2046.        End; (* Case KeySign *)
  2047.  
  2048.   9  : Case KeySign Of
  2049.        -7..-3:   If (Akey.A=NON) Then
  2050.                    Begin
  2051.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2052.                    If ChangeAKey Then Akey.A:=CORRECT;
  2053.                    End
  2054.                  Else
  2055.                    ValueSTring:=Notes[Index(value)];
  2056.         5..8 :   If (Akey.A=NON) Then
  2057.                    Begin
  2058.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2059.                    If ChangeAKey Then Akey.A:=CORRECT;
  2060.                    End
  2061.                  Else
  2062.                    ValueSTring:=Notes[Index(value)];
  2063.         Else     If (Akey.A<>NON) Then
  2064.                    Begin
  2065.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2066.                    If ChangeAKey Then Akey.A:=NON;
  2067.                    End
  2068.                  Else
  2069.                    ValueSTring:=Notes[Index(value)];
  2070.        End; (* case *)
  2071.  
  2072.   10 : Case KeySign Of
  2073.        5..8 : If Akey.A=CORRECT Then
  2074.                  Begin
  2075.                  ValueSTring:='{^'+Notes[Index(value-1)]+'}';
  2076.                  If ChangeAKey Then Akey.A:=NON;
  2077.                  End
  2078.               Else ValueSTring:=Notes[Index(value-1)];
  2079.       -8..-1: If Akey.B=CORRECT Then
  2080.                  Begin
  2081.                  ValueSTring:='{_'+Notes[Index(value+1)]+'}';
  2082.                  If ChangeAKey Then Akey.B:=NON;
  2083.                  End
  2084.               Else ValueSTring:=Notes[Index(value+1)];
  2085.  
  2086.        Else   If Akey.A=SHARP Then ValueSTring:=Notes[Index(value-1)]
  2087.               Else If Akey.B=FLAT Then ValueSTring:=Notes[Index(value+1)]
  2088.               Else
  2089.                  Case KeySIgn Of
  2090.                  -8..0  : Begin
  2091.                           ValueSTring:='{_'+Notes[Index(value+1) ]+'}';
  2092.                           If ChangeAKey Then Akey.B:=FLAT;
  2093.                           End;
  2094.                  1..8   : Begin
  2095.                           ValueSTring:='{^'+Notes[Index(value-1) ]+'}';
  2096.                           If ChangeAKey Then Akey.A:=SHARP;
  2097.                           End;
  2098.                  End;
  2099.        End; (* Case KeySign *)
  2100.  
  2101.   11 : Case KeySign Of
  2102.        -8..-1:   If (Akey.B=NON) Then
  2103.                    Begin
  2104.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2105.                    If ChangeAKey Then Akey.B:=CORRECT;
  2106.                    End
  2107.                  Else
  2108.                    ValueSTring:=Notes[Index(value)];
  2109.            8 :   If (Akey.B=NON) Then
  2110.                    Begin
  2111.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2112.                    If ChangeAKey Then Akey.B:=CORRECT;
  2113.                    End
  2114.                  Else
  2115.                    ValueSTring:=Notes[Index(value)];
  2116.         Else     If (Akey.B<>NON) Then
  2117.                    Begin
  2118.                    ValueSTring:='{='+Notes[Index(value) ]+'}';
  2119.                    If ChangeAKey Then Akey.B:=NON;
  2120.                    End
  2121.                  Else
  2122.                    ValueSTring:=Notes[Index(value)];
  2123.        End; (* case *)
  2124.  
  2125. end
  2126.  
  2127.  
  2128. End; (* ValueSTring *)
  2129.  
  2130.  
  2131. (**************************************************************************)
  2132.     Function Note2String(ThisNote:NoteRecord;
  2133.                          Clef : ClefType;
  2134.                          VAR AKey : AccKeyType) :  STRING;
  2135. (***************************************************************************)
  2136. VAR   
  2137.       i         : Word;
  2138. (*------------------------------*)
  2139.   Function HangOrBang: Char;
  2140. (*------------------------------*)
  2141. Begin
  2142. If ThisNote.Orient=UP Then HangOrBang:='u'
  2143. Else HangOrBang:='l';
  2144. End;
  2145.  
  2146. Begin
  2147. With ThisNote DO
  2148.    Case Event Of
  2149.      NOTEON,
  2150.      NOTEOFF :
  2151.          CASE NoteType Of
  2152.             WH     :   Note2String:='\wh '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2153.             WHP    :   Note2String:='\whp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2154.             WHPP   :   Note2String:='\whpp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2155.             WHPPP  :   Note2String:='\whppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2156.             H      :   Note2String:='\h'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2157.             HP     :   Note2String:='\h'+HangOrBang+'p '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2158.             HPP    :   Note2String:='\h'+HangOrBang+'pp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2159.             HPPP   :   Note2String:='\h'+HangOrBang+'ppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2160.             Q      :   Note2String:='\q'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2161.             QP     :   Note2String:='\q'+HangOrBang+'p '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2162.             QPP    :   Note2String:='\q'+HangOrBang+'pp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2163.             QPPP   :   Note2String:='\q'+HangOrBang+'ppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2164.             C      :   Note2String:='\c'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2165.             CP     :   Note2String:='\c'+HangOrBang+'p '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2166.             C3     :   Note2String:='\c'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2167.             CPP    :   Note2String:='\c'+HangOrBang+'pp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2168.             CPPP   :   Note2String:='\c'+HangOrBang+'ppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2169.             CC     :   Note2String:='\cc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2170.             CCP    :   Note2String:='\pt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+'\cc'+
  2171.                                     HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2172.             CC3    :   Note2String:='\cc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2173.             CCC    :   Note2String:='\ccc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2174.             CCCP   :   Note2String:='\pt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+'\ccc'+
  2175.                                     HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2176.             CCC3   :   Note2String:='\ccc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2177.             CCCC   :   Note2String:='\cccc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2178.             CCCCP  :   Note2String:='\pt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+'\cccc'+
  2179.                                     HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2180.             CCCC3  :   Note2String:='\cccc'+HangOrBang+' '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2181.          End; (* case *)
  2182.      VOID  :  Note2String:='';
  2183.      TXT   :  Note2String:='\uptext{' + MetaTxt^ +'} ';
  2184.      REST  :  Note2String:=RestString(NoteType,Clef);
  2185.      PEDAL : If Velocity>0 Then  Note2String:='\PED' 
  2186.              Else Note2String:='\DEP';
  2187.    End; (* case *)
  2188. End; (* Note2String *)
  2189.  
  2190.  
  2191.  
  2192. (**************************************************************)
  2193.     Function ChordNote2String(ThisNote:NoteRecord;
  2194.                               Clef : ClefType;
  2195.                               VAR AKey : AccKeyType) :  STRING;
  2196. (**************************************************************)
  2197. VAR   
  2198.       i         : Word;
  2199. Begin
  2200. With ThisNote DO
  2201.    Case Event Of
  2202.      NOTEON,
  2203.      NOTEOFF :
  2204.           CASE NoteType Of
  2205.              WH     :   ChordNote2STring:='\zw '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2206.              H      :   ChordNote2STring:='\zh '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2207.              HP     :   ChordNote2STring:='\zhp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2208.              HPP    :   ChordNote2STring:='\zhpp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2209.              HPPP   :   ChordNote2STring:='\zhppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2210.              Q      :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2211.              QP     :   ChordNote2STring:='\zqp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2212.              QPP    :   ChordNote2STring:='\zqpp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2213.              QPPP   :   ChordNote2STring:='\zqppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2214.              C      :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2215.              CP     :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2216.              C3     :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2217.              CPP    :   ChordNote2STring:='\zqpp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2218.              CPPP   :   ChordNote2STring:='\zqppp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2219.              CC     :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2220.              CCP    :   ChordNote2STring:='\zqp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2221.              CC3    :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2222.              CCC    :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2223.              CCCP   :   ChordNote2STring:='\zqp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2224.              CCC3   :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2225.              CCCC   :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2226.              CCCCP  :   ChordNote2STring:='\zqp '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2227.              CCCC3  :   ChordNote2STring:='\zq '+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2228.           End; (* case *)
  2229.      VOID : ChordNote2String:='';
  2230.      REST : ChordNote2String:=RestString(NoteType,Clef);
  2231.      TXT   : ChordNote2String:='\uptext{' + MetaTxt^ +'}';
  2232.      PEDAL : If Velocity>0 Then  ChordNote2String:='\PED' 
  2233.              Else ChordNote2String:='\DEP';
  2234.     End;
  2235. End; (* ChordNote2String *)
  2236.  
  2237.  
  2238.  
  2239. (**************************************************************)
  2240.     Function BeamNote2String(ThisNote:NoteRecord;
  2241.                              ThisBeam: BeamRecord;
  2242.                              Clef : ClefType;
  2243.                              VAR AKey : AccKeyType) :  STRING;
  2244. (**************************************************************)
  2245. VAR   
  2246.       TmpStr     : String[25];
  2247. (*------------------------------*)
  2248.   Function HOrB: Char;
  2249. (*------------------------------*)
  2250. Begin
  2251. If ThisBeam.Orient=UP Then HOrB:='h'
  2252. Else HOrB:='b';
  2253. End;
  2254.  
  2255. (*------------------------------*)
  2256.   Function BNo: Char;
  2257. (*------------------------------*)
  2258. VAR Tmp : String;
  2259. Begin
  2260. Str(ThisBeam.Numb,Tmp);
  2261. If Length(Tmp)>1 Then WriteDebugInfo('Warning: found a beam number bigger than 9 !');
  2262. Bno:=Tmp[1];
  2263. End;
  2264.  
  2265.  
  2266. Begin (* BeamNote2String *)
  2267. With ThisNote DO
  2268.    Case Event Of
  2269.      NOTEON,
  2270.      NOTEOFF :
  2271.          CASE NoteType Of
  2272.             C,C3,
  2273.             CC,CC3,
  2274.             CCC,CCC3,
  2275.             CCCC,
  2276.             CCCC3  :   Tmpstr:='\q'+HOrB+Bno+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2277.             CP,CCP,
  2278.             CCCP,
  2279.             CCCCP  :   TmpStr:='\pt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+
  2280.                                '\q'+ HOrB+Bno+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2281.             CPP    :   TmpStr:='\ppt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+
  2282.                                '\q'+HOrB+Bno+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2283.             CPPP   :   TmpStr:='\pppt '+ValueString(NoteVal,PieceContr,AKey,FALSE)+
  2284.                                '\q'+HOrB+Bno+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2285.          Else
  2286.             TmpStr:='??'+HOrB+Bno+ValueString(NoteVal,PieceContr,AKey,TRUE);
  2287.             WriteDebugInfo('Warning : found a note longer than an eighth note in a beam !');
  2288.          End; (* case *)
  2289.      VOID  : TmpStr:='';
  2290.      REST  : TmpStr:=RestString(NoteType,Clef);
  2291.      TXT   : TmpStr:='\uptext{' + MetaTxt^ +'}';
  2292.      PEDAL : If Velocity>0 Then  TmpStr:='\PED' Else TmpStr:='\DEP';
  2293.    End; (* with thisnote *)
  2294. BeamNote2String:=TmpStr;
  2295. End; (* BeamNote2String *)
  2296.  
  2297.  
  2298.  
  2299. (*****************************************************************)
  2300.   Function InitBeam(ThisBeam : BeamRecord;
  2301.                     ForceZero : Boolean;
  2302.                     VAR AKey : AccKeyType): STRING;
  2303. (*****************************************************************)
  2304. VAR
  2305.    TmpStr   :  String[25];
  2306.    IndxStr  :  STring[2];
  2307. Begin
  2308. With ThisBeam DO
  2309.    Begin
  2310.    Str(Numb,IndxStr);
  2311.    TmpStr:='\i';
  2312.    Case NoteType Of
  2313.       C,C3,CP,CPP,CPPP : TmpStr:=TmpStr+'b';
  2314.       CC,CC3,CCP       : TmpSTr:=TmpStr+'bb';
  2315.       CCC,CCC3,CCCP    : TmpSTr:=TmpStr+'bbb';
  2316.       CCCC,CCCC3,CCCCP : TmpSTr:=TmpStr+'bbbb';
  2317.   End; (* case *)
  2318.   If Orient=UP Then TmpStr:=TmpStr+'u'+IndxStr
  2319.   Else TmpStr:=TmpStr+'l'+IndxStr;
  2320.  
  2321.   TmpSTr:=TmpStr+ValueString(Pitch,PieceContr,AKey,FALSE)+'{';
  2322.  
  2323. (* determine the slope *)
  2324.   If ForceZero Then
  2325.       IndxStr:='0'
  2326.   Else
  2327.     Case Slope Of
  2328.      -127..-21 : Str(-9,IndxStr);
  2329.      -20..-18  : Str(-8,IndxStr);
  2330.      -17..-15  : Str(-7,IndxStr);
  2331.      -14..-12  : Str(-6,IndxStr);
  2332.      -11,-10   : Str(-5,IndxStr);
  2333.      -9,-8     : Str(-4,IndxStr);
  2334.      -7,-6     : Str(-3,IndxStr);
  2335.      -5,-4     : Str(-2,IndxStr);
  2336.      -3,-2     : Str(-1,IndxStr);
  2337.      -1..1     : Str(0,IndxStr);
  2338.      2,3       : Str(1,IndxStr);
  2339.      4,5       : Str(2,IndxStr);
  2340.      6,7       : Str(3,IndxStr);
  2341.      8..9      : Str(4,IndxStr);
  2342.      10..11    : Str(5,IndxStr);
  2343.      12..14    : Str(6,IndxStr);
  2344.      15..17    : Str(7,IndxStr);
  2345.      18..20    : Str(8,IndxStr);
  2346.      21..127   : Str(9,IndxStr);
  2347.     End;
  2348.   TmpSTr:=TmpStr+IndxStr+'}';
  2349.   End; (* With *)
  2350. WriteDebugInfo('Init beam with '+TmpStr);
  2351. InitBeam:=TmpStr  
  2352. End;(* InitBeam *)
  2353.  
  2354. (*****************************************************)
  2355. Function PartialBeam(ThisBeam: BeamRecord): STRING;
  2356. (*****************************************************)
  2357. VAR
  2358.     IndxStr : STring[2];
  2359.     TermBeam: String[25];
  2360. Begin
  2361. Str(ThisBeam.Numb,IndxStr);
  2362. TermBeam:='\rlap{\qsk\t';
  2363. Case ThisBeam.NoteType Of
  2364.    C,C3,CP,CPP,CPPP : TermBeam:=TermBeam+'b';
  2365.    CC,CC3,CCP       : TermBeam:=TermBeam+'bb';
  2366.    CCC,CCC3,CCCP    : TermBeam:=TermBeam+'bbb';
  2367.    CCCC,CCCC3,CCCCP : TermBeam:=TermBeam+'bbbb';
  2368. End; (* case *)
  2369.  
  2370. If ThisBeam.Orient=UP Then TermBeam:=TermBeam+'u'+IndxStr+'}'
  2371. Else TermBeam:=TermBeam+'l'+IndxStr+'}';
  2372. WriteDebugInfo('Partial terminate beam with '+TermBeam);
  2373. PartialBeam:=TermBeam;
  2374. End; (* PartialBeam *)
  2375.  
  2376.  
  2377. (*****************************************************)
  2378. Function TerminateBeam(ThisBeam: BeamRecord): STRING;
  2379. (*****************************************************)
  2380. VAR
  2381.     IndxStr : STring[2];
  2382.     TermBeam: String[25];
  2383. Begin
  2384. Str(ThisBeam.Numb,IndxStr);
  2385. If ThisBeam.Orient=UP Then TermBeam:='\tbu'+IndxStr
  2386. Else TermBeam:='\tbl'+IndxStr;
  2387. WriteDebugInfo('Terminating beam with '+TermBeam);
  2388. TerminateBeam:=TermBeam;
  2389. End; (* Terminate Beam *)
  2390.  
  2391. (***********************************************************)
  2392.   Function ChainBeam(ThisBeam,NextBeam: BeamRecord): STRING;
  2393. (***********************************************************)
  2394. VAR
  2395.     IndxStr : STring[2];
  2396.     TmpStr  : String[25];
  2397. Begin
  2398. If NextBeam.NoteType>ThisBeam.NoteType Then
  2399.   With NextBeam DO
  2400.    Begin
  2401.    Str(Numb,IndxStr);
  2402.  
  2403.    If NoNotes=1 Then (* there is only one note of higher type in next beam *)
  2404.       TmpStr:='\t'   (* instead of initializing higher order beam we insert *)
  2405.    Else              (* a terminate beam which draws the flags at the back  *)
  2406.       TmpStr:='\n';  (* of the note                                         *)
  2407.  
  2408.    Case NoteType Of
  2409.       C,C3,CP,CPP,CPPP : TmpStr:=TmpStr+'b';
  2410.       CC,CC3,CCP       : TmpSTr:=TmpStr+'bb';
  2411.       CCC,CCC3,CCCP    : TmpSTr:=TmpStr+'bbb';
  2412.       CCCC,CCCC3,CCCCP : TmpSTr:=TmpStr+'bbb';
  2413.    End; (* case *)
  2414.    If ThisBeam.Orient=UP Then TmpStr:=TmpStr+'u'+IndxStr
  2415.    Else TmpStr:=TmpStr+'l'+IndxStr;
  2416.    End (* With *)
  2417.  
  2418. Else
  2419.  
  2420.   With NextBeam DO
  2421.    Begin
  2422.    Str(Numb,IndxStr);
  2423.    TmpStr:='\t';
  2424.    Case NoteType Of
  2425.       C,C3,CP,CPP,CPPP : TmpStr:=TmpStr+'bb';
  2426.       CC,CC3,CCP       : TmpSTr:=TmpStr+'bbb';
  2427.       CCC,CCC3,CCCP    : TmpSTr:=TmpStr+'bbbb';
  2428.       CCCC,CCCC3,CCCCP : WriteDebugInfo('This cannot happen...!, error in CHaining beam');
  2429.    End; (* case *)
  2430.    If ThisBeam.Orient=UP Then TmpStr:=TmpStr+'u'+IndxStr
  2431.    Else TmpStr:=TmpStr+'l'+IndxStr;
  2432.    End; (* With *)
  2433.  
  2434. WriteDebugInfo('Chaining beam with '+TmpStr);
  2435. ChainBeam:=TmpStr;
  2436. End; (* ChainBeam *)
  2437.  
  2438.  
  2439. (*****************************************************************)
  2440.   Function InitSlurr(ThisSlurr : SlurrRecord;
  2441.                      VAR AKey : AccKeyType): STRING;
  2442. (*****************************************************************)
  2443. VAR
  2444.    TmpStr   :  String[25];
  2445.    IndxStr  :  STring[2];
  2446. Begin
  2447. With ThisSlurr DO
  2448.    Begin
  2449.    Str(Numb1,IndxStr);
  2450.    TmpStr:='\itenu'+IndxStr+ValueString(NoteVal,PieceContr,AKey,FALSE);
  2451.    End;
  2452. WriteDebugInfo('Init slurr with '+TmpStr);
  2453. InitSlurr:=TmpStr
  2454. End;(* InitSlurr*)
  2455.  
  2456. (***********************************************************)
  2457. Function TerminateSlurr(VAR ThisSlurr: SlurrRecord): STRING;
  2458. (***********************************************************)
  2459. VAR
  2460.     IndxStr : STring[2];
  2461.     TmpStr: String[25];
  2462. Begin
  2463. Str(ThisSlurr.Numb2,IndxStr);
  2464. TmpStr:='\tten'+IndxStr;
  2465. WriteDebugInfo('Terminating slurr with '+TmpStr);
  2466. If ThisSlurr.KindOf=ENDSLUR Then
  2467.    ThisSlurr.Occupied:=FALSE;
  2468. TerminateSlurr:=TmpStr;
  2469. End; (* Terminate Slurr *)
  2470.  
  2471.  
  2472.  
  2473.  
  2474.  
  2475. (****************************************************)
  2476.    Procedure FindMeasureParts(ThisMeasure : Word);
  2477. (****************************************************)   
  2478. VAR 
  2479.     ST,ET,TET,DT    : MeasureTime;
  2480.     i,curtrack       : Integer;
  2481.     N,P,Q           : NoteRecPoint;
  2482.     Done,
  2483.     PartEmpty       : Boolean;
  2484.     t1,t2           : Longint;
  2485.  
  2486. Begin
  2487. For curtrack:=1 to ntracks do
  2488.    With TrackArray[curtrack] Do
  2489.       Begin
  2490.       WriteDebugInfo('Finding parts in track '+I2S(curtrack));
  2491.       FirstNote(NoteList,N);
  2492.       Q:=N;
  2493.       LastNote(NoteList,P);
  2494.       SetTime(ST,ThisMeasure,0);
  2495.       SetTime(ET,ThisMeasure,PieceContr.TicksPerMeasure);
  2496.       SetTime(DT,0,PieceContr.PartTime);
  2497.       AddTime(ST,DT,TET);
  2498.       If N=P Then
  2499.           Begin
  2500.           WriteDebugInfo('Only one event in this track and measure ');
  2501.           Case N^.Event Of
  2502.              NOTEON,NOTEOFF : WriteDebugInfo('Note '+B2S(N^.NoteVal));
  2503.              REST           : WriteDebugInfo('Rest of type '+I2S(Ord(N^.NoteType)));
  2504.              TXT            : WriteDebugInfo('Text : '+N^.MetaTxt^);
  2505.              VOID           : WriteDebugInfo('Void event ');
  2506.              PEDAL          : WriteDebugInfo('Pedal event');
  2507.           End;
  2508.  
  2509.           Case N^.Event Of
  2510.              NOTEON,
  2511.              NOTEOFF,
  2512.              TXT    : Begin
  2513.                       PartStart[1]:=N; PartEnd[1]:=N;
  2514.                       For i:=2 to PieceContr.nparts Do
  2515.                           Begin
  2516.                           (* Reset further starts and ends..., but why here ... ? *)
  2517.                           PartStart[i]:=NIL; PartEnd[i]:=NIL;
  2518.                           End;
  2519.                       End;
  2520.              REST   : Begin
  2521.                       For i:=1 to PieceContr.nparts Do
  2522.                           Begin
  2523.                           PartStart[i]:=NIL; PartEnd[i]:=NIL;
  2524.                           End;
  2525.                       i:=PieceContr.nparts div 2;
  2526.                       PartStart[i]:=N; PartEnd[i]:=N;
  2527.                       End;
  2528.              VOID   : Begin
  2529.                       For i:=1 to PieceContr.nparts Do
  2530.                           Begin
  2531.                           PartStart[i]:=NIL; PartEnd[i]:=NIL;
  2532.                           End;
  2533.                       End;
  2534.           End; (* case *)
  2535.           End
  2536.       Else
  2537.           Begin (* N<>P *)
  2538.           For i:=1 to PieceContr.nparts do
  2539.               Begin
  2540.               WriteDebugInfo('In part '+I2S(i) +' following events:');
  2541.               PartEmpty:=TRUE;
  2542.               PartStart[i]:=NIL;
  2543.               PartEnd[i]:=NIL;
  2544.               Done:=FALSE;
  2545.                   Begin
  2546.                   t1:=TimeDiff(ST,N^.StartTime);
  2547.                   t2:=TimeDiff(TET,N^.StartTime);
  2548.                   (* does not stop at end of measure *)
  2549.                   While (t1<=0) AND (t2>0) AND NOT Done Do
  2550.                       Begin
  2551.                       Case PartEmpty Of
  2552.                          TRUE : Begin
  2553.                                 PartStart[i]:=N; PartEnd[i]:=N;
  2554.                                 PartEmpty:=FALSE;
  2555.                                 End;
  2556.                          FALSE: PartEnd[i]:=N;
  2557.                       End; (* case *)
  2558.                       Case N^.Event Of
  2559.                          NOTEON,NOTEOFF : WriteDebugInfo('Note '+B2S(N^.NoteVal));
  2560.                          REST           : WriteDebugInfo('Rest of type '+I2S(Ord(N^.NoteType)));
  2561.                          TXT            : WriteDebugInfo('Text : '+N^.MetaTxt^);
  2562.                          (* VOID           : Warning('Whoops, a void event in part....'); *)
  2563.                       End;
  2564.                       NextNote(N,N);
  2565.                       If N=Q Then Done:=TRUE;
  2566.                      t1:=TimeDiff(ST,N^.StartTime);
  2567.                      t2:=TimeDiff(TET,N^.StartTime)
  2568.                      End; (* while *)
  2569.                   End; (* Else *)
  2570.                Move(TET,ST,SizeOf(ST));
  2571.                AddTime(ST,DT,TET);
  2572.                End; (* for next i *)
  2573.           End; (* Else: N<>P *)
  2574.       End; (* with curtrack *)
  2575. WriteDebugInfo('Ready finding parts in this measure');
  2576. End; (* FindMeasureParts *)
  2577.  
  2578. (****************************************************)
  2579.     Procedure PartCreateMeasure;
  2580. (****************************************************)
  2581. VAR
  2582.      N          : NoteRecPoint;
  2583.      i,curtr    : integer;
  2584.      Ms         : Array[1..MAXPARTS] Of String;
  2585.      CurLength,
  2586.      MaxCnt,
  2587.      EventCnt   : Integer;
  2588.      MaxCnts    : Array[1..MAXPARTS] Of Integer;
  2589.      BeamsOccured  : Boolean;
  2590.  
  2591.  
  2592. (*-------------------------------*)
  2593.    Function Seperator : String;
  2594. (*-------------------------------*)
  2595. Var TmpStr : String;
  2596. Begin
  2597. TmpStr:='';
  2598. If curtr=ntracks Then { we are at the end of the current range ...}
  2599.       If ntracks>1 Then
  2600.           Begin (* curtr=ntracks *)
  2601.           If (NOT TrackArray[TrackOrder[ntracks]].Skip) AND
  2602.              (NOT TrackArray[TrackOrder[ntracks-1]].Skip) Then
  2603.                If TrackArray[TrackOrder[ntracks]].Instrument AND
  2604.                   TrackArray[TrackOrder[ntracks-1]].Instrument Then
  2605.                      TmpStr:='|'
  2606.                Else
  2607.                      TmpStr:='&'
  2608.           End
  2609.       Else
  2610.           TmpStr:=''
  2611. Else
  2612.       Begin
  2613.       If curtr=1 Then
  2614.              Begin  (* curtr=1 *)
  2615.              TmpStr:=''
  2616.              End
  2617.        Else
  2618.               Begin (* curtr>1 & curtr<ntracks *)
  2619.               If NOT TrackArray[TrackOrder[curtr-1]].Skip Then
  2620.                     Begin
  2621.                     If TrackArray[TrackOrder[curtr]].Instrument AND
  2622.                        TrackArray[TrackOrder[curtr-1]].Instrument Then
  2623.                           TmpStr:='|'
  2624.                     Else
  2625.                           TmpStr:='&'
  2626.                     End;
  2627.               End;
  2628.        End;
  2629. Seperator:=TmpStr;
  2630. End; (* Seperator *)
  2631.  
  2632.  
  2633. (*--------------------------------------------------------*)
  2634.    Function GetNoteStr(VAR ThisTrack : TrackRecord) : String;
  2635. (*--------------------------------------------------------*)
  2636. Var  Astring  : String;
  2637.      j        : Integer;
  2638.      TmpTime  : MeasureTime;
  2639. Begin
  2640. Astring:='';
  2641. SetTime(TmpTime,MeasureCount+1,0);
  2642. With ThisTrack Do
  2643.    Begin
  2644.  
  2645.    IF SLurring Then
  2646.       Begin
  2647.       j:=IsSlurred(N,ThisTrack);
  2648.       If j>0 Then
  2649.          With SlurrArray[j] Do
  2650.             Case KindOf Of
  2651.                STARTSLUR : Begin
  2652.                            Astring:=Astring+InitSlurr(SlurrArray[j],AccKey);
  2653.                            End;
  2654.                REPEATSLUR: Begin
  2655.                            Astring:=Astring+TerminateSlurr(SlurrArray[j]);
  2656.                            Astring:=Astring+InitSlurr(SlurrArray[j],AccKey);
  2657.                            End;
  2658.                ENDSLUR   : Begin
  2659.                            Astring:=Astring+TerminateSlurr(SlurrArray[j]);
  2660.                            End;
  2661.             ENd; (* case *)
  2662.       End; (* slurring *)
  2663.  
  2664.  
  2665.    If Beam Then
  2666.       Begin
  2667.       BeamsOccured:=TRUE;
  2668.       If N=BeamArray[BeamPt].EndNote Then
  2669.          If BeamArray[BeamPt].CHain2Next Then
  2670.              Begin
  2671.              Astring:=Astring+ChainBeam(BeamArray[BeamPt],
  2672.                                          BeamArray[BeamPt+1]);
  2673.  
  2674.              Inc(BeamPt);
  2675.              
  2676.              If N=BeamArray[BeamPt].EndNote Then (* end this beam immediately *)
  2677.                  Astring:=Astring+TerminateBeam(BeamArray[BeamPt]);
  2678.  
  2679.              End
  2680.          Else
  2681.              Begin
  2682.              Astring:=Astring+TerminateBeam(BeamArray[BeamPt]);
  2683.              End
  2684.         End (* if beam *)
  2685.    Else
  2686.       If N=BeamArray[BeamPt].StartNote Then
  2687.           Begin
  2688.           BeamsOccured:=TRUE;
  2689.           If (BeamArray[BeamPt].NoNotes=1) AND
  2690.              (BeamArray[BeamPt].CHain2Next) AND
  2691.              (BeamArray[BeamPt].NoteType>BeamArray[BeamPt+1].NoteType) Then
  2692.              Begin
  2693.              Astring:=Astring+InitBeam(BeamArray[BeamPt+1],ForceZeroBeams,AccKey);
  2694.              Astring:=Astring+PartialBeam(BeamArray[BeamPt]);
  2695.              Inc(BeamPt);
  2696.              End
  2697.           Else
  2698.              Astring:=Astring+InitBeam(BeamArray[BeamPt],ForceZeroBeams,AccKey);
  2699.           Beam:=TRUE;
  2700.           End;
  2701.  
  2702.  
  2703.    If  Chord  Then
  2704.         Begin
  2705.         If N=ChordArray[ChordPt].EndNote Then
  2706.              Begin
  2707.              Chord:=FALSE;
  2708.              WriteDebugInfo('Hit the end of the chord');
  2709.              Inc(ChordPt);
  2710.              If Beam Then
  2711.                  Begin
  2712.                  BeamsOccured:=TRUE;
  2713.                  Astring:=Astring+BeamNote2String(N^,BeamArray[BeamPt],Clef,AccKey);
  2714.                  Inc(EventCnt);
  2715.                  If N=BeamArray[BeamPt].EndNote Then
  2716.                     Begin
  2717.                     Beam:=FALSE;
  2718.                     Inc(BeamPt);
  2719.                     End;
  2720.                  End
  2721.              Else
  2722.                  Begin
  2723.                  Astring:=Astring+Note2String(N^,Clef,AccKey);
  2724.                  Inc(EventCnt);
  2725.                  End
  2726.              End
  2727.         Else
  2728.              Astring:=Astring+ChordNote2String(N^,Clef,AccKey);
  2729.         End (* If NtArPoint... *)
  2730.  
  2731.    Else
  2732.  
  2733.         Begin
  2734.         If N=ChordArray[ChordPt].StartNote Then
  2735.                  Begin
  2736.                  WriteDebugInfo('Hit start of chord ');
  2737.                  Chord:=TRUE;
  2738.                  Astring:=Astring+ChordNote2String(N^,Clef,AccKey)
  2739.                  End
  2740.             Else
  2741.                  If Beam Then
  2742.                     Begin
  2743.                     BeamsOccured:=TRUE;
  2744.                     Astring:=Astring+BeamNote2String(N^,BeamArray[BeamPt],Clef,AccKey);
  2745.                     Inc(EventCnt); BeamsOccured:=TRUE;
  2746.                     If (N=BeamArray[BeamPt].EndNote) AND
  2747.                        (NOT BeamArray[BeamPt].Chain2Next) Then
  2748.                        Begin
  2749.                        Beam:=FALSE;
  2750.                        Inc(BeamPt);
  2751.                        End;
  2752.                     End
  2753.                  Else
  2754.                     Begin
  2755.                     Astring:=Astring+Note2String(N^,Clef,AccKey);
  2756.                     Inc(EventCnt);
  2757.                     End
  2758.         End; (* Else *)
  2759.    End; (* With thistrack *)
  2760. GetNoteStr:=Astring;
  2761. End; (* GetNoteStr *)
  2762.  
  2763.  
  2764.  
  2765. Begin (* PartCreateMeasure *)
  2766. For i:=1 To ntracks do
  2767.  With TrackArray[i] Do
  2768.    Begin
  2769.    Chord:=FALSE;
  2770.    Beam:=FALSE;
  2771.    ChordPt:=1;
  2772.    BeamPt:=1;
  2773.    End;
  2774.  
  2775. CurLength:=0;
  2776.  
  2777. For i:=1 to PieceContr.nparts Do
  2778.     Begin
  2779.     MaxCnts[i]:=0; BeamsOccured:=FALSE;
  2780.     Ms[i]:='';
  2781.     For curtr:=ntracks downto 1 do
  2782.         With TrackArray[TrackOrder[curtr]] Do
  2783.             Begin
  2784.             EventCnt:=0;
  2785.             If NoteList.Size>MeasureMaxCnt Then MeasureMaxCnt:=NoteList.Size;
  2786.             If Not Skip Then
  2787.                 Begin
  2788.                 N:=PartStart[i];
  2789.                 If N<>NIL Then
  2790.                     Begin
  2791.                     Ms[i]:=Ms[i]+GetNoteStr(TrackArray[TrackOrder[curtr]]);
  2792.                     While N<>PartEnd[i] Do
  2793.                         Begin
  2794.                         NextNote(N,N);
  2795.                         Ms[i]:=Ms[i]+GetNoteStr(TrackArray[TrackOrder[curtr]]);
  2796.                         End;
  2797.                     End;
  2798.                  End;
  2799.             Ms[i]:=Ms[i]+Seperator;
  2800.  
  2801.             If EventCnt>MaxCnts[i] Then MaxCnts[i]:=EventCnt;
  2802.  
  2803.             End;
  2804.  
  2805.     (* MaxCnts[i] contains the maximum number of notes in any of the tracks' parts *)
  2806.     (* we use it to update the total         *)
  2807.     (* cumulative length of the score line *)
  2808.  
  2809.     
  2810.     If BeamsOccured Then
  2811.        Begin
  2812.        Ms[i]:='\NOtes'+Ms[i]+'\enotes\relax';
  2813.        Inc(CurLength,2*MaxCnts[i]*Elemskip);
  2814.        End
  2815.     Else
  2816.        Case MaxCnts[i] Of
  2817.           0      :   Begin End; (* empty parts are not written ... *)
  2818.           1..2   :   Begin
  2819.                      Ms[i]:='\NOtes'+Ms[i]+'\enotes\relax';
  2820.                      Inc(CurLength,2*(MaxCnts[i])*Elemskip);
  2821.                      ENd;
  2822.           3..5   :   Begin
  2823.                      Ms[i]:='\Notes'+Ms[i]+'\enotes\relax';
  2824.                      Inc(CurLength,Round(1.4*((MaxCnts[i])*Elemskip)));
  2825.                      End;
  2826.           6..10  :   Begin
  2827.                      Ms[i]:='\notes'+Ms[i]+'\enotes\relax';
  2828.                      Inc(CurLength,((MaxCnts[i])*Elemskip));
  2829.                      End;
  2830.           11..15 :   Begin
  2831.                      Ms[i]:='\notes'+Ms[i]+'\enotes\relax';
  2832.                      Inc(CurLength,((MaxCnts[i])*Elemskip));
  2833.                      End;
  2834.           16..20 :   Begin
  2835.                      Ms[i]:='\notes'+Ms[i]+'\enotes\relax';
  2836.                      Inc(CurLength,((MaxCnts[i])*Elemskip));
  2837.                      End;
  2838.           Else       Begin
  2839.                      Ms[i]:='\notes'+Ms[i]+'\enotes\relax';
  2840.                      Inc(CurLength,((MaxCnts[i])*Elemskip));
  2841.                      ENd;
  2842.        End; (* case *)
  2843.  
  2844.     If (i>1) Then If NOT BeamsOccured Then
  2845.        Ms[i]:='\temps'+Ms[i];
  2846.  
  2847.     End; (* For Next nparts *)
  2848.  
  2849. (* All parts are processed, a full measure has been written to disk   *)
  2850. (* Now we must find out if we have to write a \alapage and \alaligne  *)
  2851. (* CumLength now contains the length of the total lines               *)
  2852. If MeasureCount>0 Then
  2853.    Begin
  2854.    WriteDebugInfo('Curlength='+I2S(CurLength)+'pt, Cumlength='+I2S(CumLength)+
  2855.                   'pt, Cumheight='+I2S(CumHeight));
  2856.    If (CumLength+CurLength>=ScoreWidth) Then
  2857.       Begin
  2858.       If (CumHeight+ScoreSep+LineHeight*(ntracks-NoOfSkips)>=ScoreHeight) Then
  2859.          Begin
  2860.          WriteLn(TexFile,'\alapage');
  2861.          Inc(NoOfPages);
  2862.          CumHeight:=200+(ScoreSep+LineHeight*(ntracks-NoOfSkips));
  2863.          CumLength:=Indent+CurLength;
  2864.          WriteDebugInfo('so... inserting \alapage');
  2865.          End
  2866.       Else
  2867.          Begin
  2868.          WriteLn(TexFile,'\alaligne');
  2869.          Inc(CumHeight,(ScoreSep+LineHeight*(ntracks-NoOfSkips)));
  2870.          CumLength:=Indent+CurLength;
  2871.          WriteDebugInfo('so... inserting \aligne');
  2872.          End
  2873.       End
  2874.    Else
  2875.       Begin
  2876.       WriteLn(TeXFile,'\barre');
  2877.       Inc(CumLength,BarIndent+CurLength);
  2878.       WriteDebugInfo('so... inserting \barre');
  2879.       End;
  2880.    End (* If MeasureCount>0 *)
  2881. Else
  2882.    Begin (* MeasureCOunt=0 *)
  2883.    Inc(CumLength,1*Elemskip+CurLength);
  2884.    End;
  2885.  
  2886. For i:=1 To PieceContr.nparts Do
  2887.     If MaxCnts[i]>0 Then
  2888.        Begin
  2889.        WriteLn(TexFile,Ms[i]);
  2890.        WriteDebugInfo('Tail of MeasureString : ' + Ms[i]);
  2891.        End
  2892.     Else
  2893.        WriteDebugInfo('Empty part ');
  2894.  
  2895. End; (* PartCreateMeasure *)
  2896.  
  2897. (**********************************************)
  2898.     Procedure CheckControls(ThisMsre : Integer);
  2899. (**********************************************)
  2900. VAR    N,P : NoteRecPoint;    
  2901. Begin 
  2902. With TrackArray[1] Do (* TrackArray record 1 contains META events *)
  2903.   If NoteList.Size>0 Then (* we assume that there is only one control *)
  2904.     Begin                  (* per measure                              *)
  2905.     FirstNote(NoteList,N);
  2906.     If (N^.StartTime.Measure=ThisMsre) Then
  2907.        Case N^.Event OF
  2908.            KEYSIGN,
  2909.            SIGNATURE  :  ChangeContext(N);
  2910.        End; (* case *)
  2911.     End; (* If *)
  2912. End;             
  2913.  
  2914.  
  2915.  
  2916. (**********************************************)
  2917. (*                                            *)
  2918. (*           MAIN BLOCK                       *)
  2919. (*                                            *)
  2920. (**********************************************)
  2921.  
  2922. Begin 
  2923. InstallNewErrorExit;
  2924. Notes:='???????????????????ABCDEFGHIJKLMNabcdefghijklmnopqrstuvwxyz???????';
  2925. CPosition:=36;
  2926.       Begin
  2927.       DisplayLicense;
  2928.       Initialize;
  2929.       TmpStr:=ReadString(HlpFilRec,4);
  2930.       WriteDebugInfo(TmpStr);
  2931.       IF TmpStr<>'MThd' Then ErrorExit(2);
  2932.       ALongInt:=ReadLongInt(HlpFilRec);
  2933.       WriteDebugInfo('HeaderNo='+LI2S(AlongInt));
  2934.       IF AlongInt<>6 THEN ErrorExit(2);
  2935.       FileFormat:=ReadInteger(HlpFilRec);
  2936.       WriteDebugInfo('MidiFile is in format type : '+B2S(FileFormat)); (* this is OK *)
  2937.       Case FileFormat of 
  2938.          0 :  Warning('This is a type 0 MIDI file, no warranties about the result...');     
  2939.          2 :  ErrorExit(5);
  2940.       End;
  2941.  
  2942.       ntracks:=ReadInteger(HlpFilRec);
  2943.       WriteDebugInfo(' Found '+I2S(ntracks)+' tracks in this file');
  2944.       If NoOFSkips>0 Then WriteDebugInfo('Skipping '+B2S(NoOfSkips)+' of them');
  2945.       If OrderIndex>1 Then If OrderIndex<>ntracks Then ErrorExit(7);
  2946.       CumHeight:=300+(ScoreSep+LineHeight*(ntracks-NoOfSkips));;
  2947.  
  2948.       WriteTexHeader;
  2949.       With PieceContr Do
  2950.          Begin
  2951.          Division:=ReadInteger(HlpFilRec);
  2952.          WriteDebugInfo(' Division : '+I2S(Division));
  2953.          Num:=4;Den:=2;
  2954.          TicksPerMeasure:=4*Division*Num div Power(2,Den);
  2955.          WriteDebugInfo('Ticks per Measure :'+I2S(TicksPerMeasure));
  2956.          PartTime:=TicksPerMeasure div Num;
  2957.          nparts:=TicksPerMeasure div PartTime;
  2958.          Twindow:=Division div 16;
  2959.          End;
  2960.  
  2961.       InitFilePosns(ntracks); (* find the starts of the tracks in the file *)
  2962.  
  2963.       MeasureCount:=-1;
  2964.       repeat                    
  2965.          INC(MeasureCount);
  2966.          WriteDebugInfo(' starting to read Measure '+W2S(MeasureCount));
  2967.          Write('['+W2S(MeasureCount)+']');
  2968.          If (MeasureCount>0) AND (MeasureCount MOD 19 =0) Then WriteLn('');
  2969.          For curtrack:=1 to ntracks do
  2970.            Begin
  2971.            With TrackArray[curtrack] Do
  2972.              Begin
  2973.              If NOT EndOfTrackReached(TrackArray[curtrack]) Then
  2974.                Begin
  2975.  
  2976.                WriteDebugInfo('Starting to read from track :'+I2S(curtrack));
  2977.                (* LastNoteOffTime.Measure:=MeasureCount; *) (* to get a correct rest *)
  2978.                (* LastNoteOffTime.Mpart:=0; *)
  2979.  
  2980.                QuitTrack:=FALSE;
  2981.                
  2982.                (* Transfer all spilled events back to the note stack *) 
  2983.                If SpillList.Size>0 Then
  2984.                     WriteDebugInfo('Transfering '+W2S(SpillList.Size)+' notes from spillist');
  2985.                While SpillList.Size>0 Do 
  2986.                   Begin
  2987.                   LastNote(SpillList,N);
  2988.                   Remove(SpillList,N);
  2989.                   Append(NoteList,N);
  2990.                   WriteDebugInfo('Note : '+B2S(N^.NoteVal)+
  2991.                               ' from '+W2S(N^.StartTime.Measure)+':'+LI2S(N^.StartTime.MPart)+
  2992.                               ' to '+W2S(N^.EndTime.Measure)+':'+LI2S(N^.EndTime.MPart));
  2993.  
  2994.                   If SPillList.Size=0 Then
  2995.                      Begin
  2996.                      If N^.StartTime.Measure>MeasureCount Then
  2997.                      QuitTrack:=TRUE;
  2998.                      ENd;
  2999.                   End;
  3000.                                     
  3001.  
  3002.                If (NOT QuitTrack) AND (NOT EndOfTrackRead) Then
  3003.                    Repeat
  3004.                       ReadDeltaTime(TrackArray[curtrack]);
  3005.                       If (CurTime.Measure>MeasureCount+1) OR 
  3006.                           ((CurTime.Measure=MeasureCount+1) AND
  3007.                            (CurTime.Mpart>QuantTime div 2)) Then
  3008.                          Begin
  3009.                          QuitTrack:=TRUE;
  3010.                          End;
  3011.                       ReadEvent(TrackArray[curtrack]);
  3012.                       INC(SafetyCounter);
  3013.                    until QuitTrack OR EndOfTrackRead;
  3014.  
  3015.                (* Transfer SpillEvents to SpillList *)
  3016.                (* only NoteOn can be transferred...*)
  3017.                (* a NoteOff can be maintained, but *)
  3018.                (* note must than be slurred to     *)
  3019.                (* next measure                     *)
  3020.                
  3021.                (* removing notes to spillist not correct yet.... *)
  3022.                (*  Hans : 24-3-92 *)
  3023.                
  3024.                If NoteList.Size>0 Then
  3025.                   Begin
  3026.                   SetTime(TempTime,MeasureCount+1,0);
  3027.                   LastNote(NoteList,N);
  3028.                   While (NoteList.Size>0) AND
  3029.                         ( TimeDiff(TempTime,N^.StartTime)<=0)  Do
  3030.                        Begin
  3031.                        WriteDebugInfo('Transfering note'+B2S(N^.NoteVal)+' to spillist');
  3032.                        Remove(NoteList,N);
  3033.                        Append(SpillList,N); 
  3034.                        If NoteList.Size>0 Then
  3035.                           Begin
  3036.                           LastNote(NoteList,N);                      
  3037.                           WriteDebugInfo('Last note now : '+B2S(N^.NoteVal));
  3038.                           End;
  3039.                        End;
  3040.                   End;
  3041.  
  3042.                End
  3043.              Else
  3044.                WriteDebugInfo('Track '+I2S(curtrack)+' was already empty');
  3045.  
  3046.              (* see if there was any note at all in the track ... *)
  3047.              (* this is not OK....????? 26-3-'92 *)
  3048.              If (NoteList.Size=0) Then
  3049.                 Begin
  3050.                 SetTime(CurTime,MeasureCount,PieceContr.TicksPerMeasure);
  3051.                 InsertRest(TrackArray[curtrack]);
  3052.                 End;
  3053.  
  3054.              End; (* With TrackArray *)
  3055.            End; (* For loop curtrack *)
  3056.      
  3057.  
  3058.      (* Process the current measure in the Track's note arrays *)
  3059.          WriteLn(TexFile,'%measure ',MeasureCount+1);
  3060.  
  3061.      (* see if there are any control events to start in this measure *)
  3062.  
  3063.          CheckControls(MeasureCount);
  3064.  
  3065.          BeamIndex:=0;
  3066.          For curtrack:=ntracks downto 1 do
  3067.            Begin
  3068.            With TrackArray[curtrack] Do
  3069.               If (NOT Skip) AND (NoteList.Size>0) Then
  3070.                  Begin
  3071.                  WriteDebugInfo('Start handling events in track :'+I2S(curtrack));
  3072.                  FindNoteTypes(TrackArray[TrackOrder[curtrack]],MeasureCount);
  3073.                  ChordFind(TrackArray[TrackOrder[curtrack]]);
  3074.                  FindSLurrNote(TrackArray[TrackOrder[curtrack]],MeasureCount);
  3075.                  BeamFind(TrackArray[TrackOrder[curtrack]]);
  3076.                  End;
  3077.            End;
  3078.  
  3079.            FindMeasureParts(MeasureCount);
  3080.  
  3081.            PartCreateMeasure;
  3082.  
  3083.            CleanUpTracks;
  3084.  
  3085.        until AllTracksRead(ntracks) OR
  3086.              (SafetyCounter>10000);
  3087.  
  3088.       WriteLn(TexFile,'\finmorceau');
  3089.       WriteLn(TexFile,'\bye');
  3090.       WriteLn('');
  3091.       WriteLn('Total : '+I2S(NoOfPages)+' pages coded');
  3092.       end;
  3093. end.
  3094.